0

我开始学习C,但我不明白我做错了什么。这是一个返回 pid+".data" 的函数的简单代码。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

char * getfilename(){
    char name[60];
    sprintf(name,"%i.data",getpid());
    return name;
}

void main(){
    char* name = getfilename();
    printf("%s",name);
}

输出:��#�a

所以我想我做错了什么。

4

6 回答 6

4
char * getfilename(){
    char name[60];
    sprintf(name,"%i.data",getpid());
    return name;
}

返回后您无法访问name对象getfilename。自动对象的生命周期最后name结束。在函数返回后访问它是未定义的行为。getfilename}

作为临时修复,您可以指定nameasstatic并且它将起作用。但是您应该做的是让getfilename函数接受将写入文件名的指针参数。

编辑:

为什么我不建议使用strdup

  • strdup不是标准 C 函数。strdup生活在 POSIX 世界中。出于可移植性的原因,我更喜欢使用标准 C 函数。
  • strdup执行隐藏malloc呼叫,您不必忘记执行free. malloc这与标准 C 库中从不调用(或实际上从未出现调用)的所有函数相反mallocstrdup是一个糟糕的 API 设计。
  • strdup正在执行字符串的副本。为什么需要执行额外的复制?只需将字符串写在您可以检索它的地方。
于 2012-11-12T13:07:52.323 回答
3

一种解决方案是使用strdup,即更改:

return name;

到:

return strdup(name);

这会使用动态内存分配(即malloc)复制您的临时(本地)字符串。

当然,您必须确保在完成后释放该字符串。

你需要:

#include <string.h> // strdup()
#include <stdlib.h> // free()
于 2012-11-12T13:11:48.023 回答
1
char name[60] 

存在于堆栈上,但只要在其内部getfilename()被释放,因此对它的任何引用(也由返回getfilename())将变为无效。

于 2012-11-12T13:10:10.887 回答
1

char name[60]是一个局部变量,在函数调用时分配,返回时释放。当您尝试返回它时,您实际上是在返回它的地址(毕竟数组主要是指针算术的语法糖)。现在,您的调用者有一个指向已空闲内存块的指针,因此可能包含垃圾。

于 2012-11-12T13:10:58.143 回答
1

你不能name从你的函数返回数组getfilename,因为它是一个(常规)局部变量,当函数返回时这些变量会被清除。因此,当您返回main并尝试打印返回值时,name那里的指针指向已被重用于其他目的的内存块。

这个问题有几种解决方案:

  1. namegetfilename static。_ 这将确保它的调用寿命更长getfilename并且可以安全地返回,但缺点是所有调用都getfilename使用相同的缓冲区。
  2. 动态分配数组malloc(完成后不要忘记清理free它)
  3. 传递缓冲区以将值存储为参数。
于 2012-11-12T13:15:36.397 回答
0

如其他答案中所述,您不能返回指向函数堆栈中某处的指针。

您可以简单地将分配的数组传递给getfilename()函数。您可以按如下方式重写程序。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void getfilename(char * name)
{

    sprintf(name,"%i.data",getpid());
}

int main(void)
{
    char name[60];
    getfilename(name);
    printf("%s\n",name);
    return 0;
}

这应该可以正常工作。

于 2012-11-12T14:20:31.303 回答