Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Malloc改变单独函数中未初始化变量的行为?_C_Memory Management_Malloc_Programming Languages_Compiler Optimization - Fatal编程技术网

Malloc改变单独函数中未初始化变量的行为?

Malloc改变单独函数中未初始化变量的行为?,c,memory-management,malloc,programming-languages,compiler-optimization,C,Memory Management,Malloc,Programming Languages,Compiler Optimization,这是我的编程语言概念/实现类的一个问题。给定以下C代码段: void foo() { int i; printf("%d ", i++); } void main() { int j; for (j = 1; j <= 10; j++) foo(); } void foo() { int i; printf(“%d”,i++); } void main() { int j; 对于(j=1;j,foo中的变量i

这是我的编程语言概念/实现类的一个问题。给定以下C代码段:

void foo()  
{ 
    int i; 
    printf("%d ", i++); 
} 
void main()  
{ 
    int j; 
    for (j = 1; j <= 10; j++)  
        foo(); 
}
void foo()
{ 
int i;
printf(“%d”,i++);
} 
void main()
{ 
int j;

对于(j=1;j,foo中的变量i只是未初始化的,未初始化的值在进入块时具有不确定的值。您看到它打印某些值的方式完全是一致的,要编写符合标准的C,您永远不应该依赖这种行为。在使用它之前,您应该始终初始化自动变量

根据c11std 6.2.4p6:

对于不具有可变长度数组类型的对象,其生存期从进入与其关联的块开始,一直到该块的执行以任何方式结束。(进入封闭块或调用函数将暂停但不结束当前块的执行。)如果以递归方式输入块,则每次都会创建对象的新实例。对象的初始值是不确定的。如果为对象指定了初始化,则每次在执行块时达到声明或复合文字时都会执行该初始化;否则,每次值都会变为不确定已到达声明。

不可能有“正确”的解决方案。但可能有一类解决方案适用于特定的CPU体系结构、ABI、编译器和编译器选项

将代码更改为类似这样的内容将产生改变堆栈上方内存的效果,这将以一种有针对性的方式影响许多(如果不是大多数的话)环境

void foo()  
{ 
    int i; 
    printf("%d ", i++); 
} 
void main()  
{ 
    int j;
    int a [2];

    for (j = 1; j <= 10; j++)
    {
        foo();
        a [-5] = j * 100;
    }
}
a[-5]
是用于开销和跨越两个函数的变量的堆栈字数。有返回地址、保存的堆栈链接值等。当foo()写入[-5]时,堆栈可能如下所示:

i
saved stack link
return address
main's j
(must be something else)
main's a[]
第二次尝试时,我猜到了-5,-4是我的第一个猜测。

当您从
main()
调用
foo()
时,(未初始化的)变量
I
被分配到内存地址。在原始代码中,它恰好为零(在您的机器上,使用您的编译器、您选择的编译选项、您的环境设置,并考虑到月球的当前阶段——当其中任何一个或无数其他因素发生变化时,它可能会发生变化)

通过在调用
foo()
之前调用另一个函数,您允许另一个函数用不同的值覆盖
foo()
将用于
i
的内存位置。它不能保证更改;如果运气不好,您可以用另一个零替换零

您或许可以使用另一个功能:

static void bar(void)
{
    int j;
    for (j = 10; j < 20; j++)
        printf("%d\n", j);
}
静态空栏(void)
{
int j;
对于(j=10;j<20;j++)
printf(“%d\n”,j);
}
在调用
foo()
之前调用它会改变
i
中的值。调用
malloc()
也会改变事情。调用几乎任何函数都可能会改变它


但是,它必须是(re)强调原始代码充满了未定义的行为,调用其他函数并不会减少未定义的行为。任何事情都可能发生,而且它是有效的。

未初始化的值似乎保留了过去调用的值,原因是它位于堆栈上,并且每次调用时堆栈指针恰好具有相同的值这就是所谓的不合作

代码更改值的原因可能是您开始调用其他函数:
malloc
free
。它们的内部堆栈变量与
foo()
中的
i
使用相同的位置


至于优化,像这样的小程序有完全消失的危险。GCC或Clang可能会决定,因为使用未初始化的变量是未定义的行为,编译器有权完全删除代码。或者它可能会将
i
放在一个寄存器中设置为零。然后决定所有printf调用的输出为零n确定您的整个程序只是一个单一的
put(“0000000000”)
调用。

您被问到的确切问题是什么?在
foo()中没有
i
)< /代码>可以从别处初始化,除非某种形式的软糖使得未定义的行为表现得像你认为的那样。在C中,<代码> I/code >将不会在任何系统上初始化,当然不是大多数。@ Weevave:问题的确切措辞是:考虑下面的C程序:[代码块如上]。子程序foo中的局部变量i从未初始化。但是,在许多系统上,变量i似乎在调用foo之间“记住”其值,程序将打印0 1 2 3 4 5 6 7 8 9。(a)建议对此行为的解释。(b)更改上述代码(不修改函数foo)更改此行为。我的测试不会通过
9
打印
0
。这是未定义的行为。因此,您所能做的就是将其更改为另一个未定义的行为。它与
malloc
无关,与调用
foo
时覆盖存储
i
的堆栈位置有关。请参见.T这正是我所担心的,对于一个家庭作业来说,这不是一个构思得非常好的问题。至于未定义的行为,我只在我的机器上用gcc测试了它,它打印了0-9。无论如何,谢谢你,问题不是代码是否符合标准C,而且所有人都认为,这是一个糟糕的代码。我正在学习的类是它的前身编译器设计以及上述代码完全合法这一事实在设计编译器时必须加以处理。我了解良好的编程标准,不欣赏这种赞助人的反应。我发现奇怪的是,如果一个“goto”从使用变量后的一个点跳到声明变量前的一个点,再跳到第二个“goto”跳过其声明后,值仍保留
i
saved stack link
return address
main's j
(must be something else)
main's a[]
static void bar(void)
{
    int j;
    for (j = 10; j < 20; j++)
        printf("%d\n", j);
}