Wul*_*ulf 6 c stack dynamic-memory-allocation stack-memory
我正在读这本书:“ C von A bis Z”。
有这个例子。
/* ptr14.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Fehler: Funktion gibt die Adresse
* einer lokalen Variablen zurück. */
/* [ Error: Function returns the address of a
a local variable. ] */
// ...
/* Möglichkeit2: Speicher vom Heap verwenden */
/* [ Option2: Use memory from the heap ] */
char *test3(void){
char *buffer = (char *) malloc(10);
strcpy(buffer, "testwert");
return buffer;
}
/* Möglichkeit3: Einen Zeiger als Argument übergeben */
/* [ Option3: Pass a pointer as argument ] */
char *test4(char *ptr){
char buffer[10];
ptr = buffer;
strcpy(buffer, "testwert");
return ptr;
}
int main(void) {
char *ptr;
/* ... */
ptr = test3();
printf("test3: %s\n", ptr);
test4(ptr);
printf("test4: %s\n", ptr);
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
我了解作者在谈论的问题。
为什么test4解决方案有效?
如果我理解正确,不是吗
char buffer[10];在堆栈上分配buffer给my ptr(在先前作用域中居住)ptr = buffer;我的期望:
带ptron的点buffer应该是错误的,因为该范围应该被破坏/清除。
我的想法出了什么问题?
编辑1
我换test4(ptr);到ptr = test4(ptr),它仍然有效?
仍然不知道为什么test4(char* ptr)会起作用...
您的想法没有错-您是绝对正确的。好的工作,您现在比使用本书的人更懂C编程语言。
这本书是一文不值的-第三修订版,它以令人毛骨悚然的例子教授了3年前的过时C语言。你正好是幸运与test4。将数组的第一个元素的地址放在某些编译器中只会抑制警告,并且数组恰好位于堆栈上的正确位置且不会被覆盖。但是GCC 8.3并没有被中间变量所欺骗。
在功能上
char *test4(char *ptr){
char buffer[10];
ptr = buffer;
strcpy(buffer, "testwert");
return ptr;
}
Run Code Online (Sandbox Code Playgroud)
ptr在函数内部使用绝不会影响函数外部的指针。它的工作在原来的例子,因为ptr是仍指向从返回的值test3,这是从堆分配。当您将其替换ptr = test4(ptr);为ptr变量时,将获得完全不确定的行为,因为它现在指向变量的生命周期。当发生未定义的行为时,程序可能会执行任何操作,包括(C11 3.4.3p1):
[...]完全忽略这种情况,结果不可预测[...]
具有“无法预测的结果”,包括其“按预期”运行的可能性。
上一个公告点列出了以下选项之一:
- [Sie verwenden] einen beim Aufruf der Funktion als ArgumentübergebenenPuffer [...]
即[您将使用]作为参数传递给函数的缓冲区。对于此选项,test4应阅读
// use the **array** starting from *ptr
char *test4(char *ptr){
// use a **different** string here so that you can verify
// that it actually *works* (max 9 characters!)
strcpy(ptr, "testval 4");
return ptr;
}
Run Code Online (Sandbox Code Playgroud)
甚至也许
void test4(char *ptr){
strcpy(ptr, "testval 4");
}
Run Code Online (Sandbox Code Playgroud)
文档指出,在调用此函数之前,ptr应指向至少10 chars 的数组。