对malloced字符串的赋值行为很奇怪

Yut*_*ing -4 c

这是代码,它是C代码.并请说明="字符串"的返回值

    char * p = (char*) malloc(sizeof(char) * 100);
    p = "hello";   
    *(p+1) = '1';
    printf("%s", p);
    free(p);
Run Code Online (Sandbox Code Playgroud)

Bas*_*tch 6

请注意,p = "hello";不复制任何字符串,只是将指针设置为6字节文字字符串p地址"hello".复制字符串使用strncpystrcpy(读取strncpy(3) ...)但是害怕缓冲区溢出.

所以你也是

 char * p = malloc(100);
Run Code Online (Sandbox Code Playgroud)

它分配一个能够容纳100个字节的内存区域.让我们假装malloc成功(读取malloc(3) ...)并返回地址0x123456(通常,具体地址不能从一次运行到下一次运行,例如因为ASLR).

然后你分配,p = "hello";所以你忘了地址0x123456(你现在有一个内存泄漏),你p输入6字节文字字符串的地址"hello"(让我们想象它是0x2468a).

后来机器执行的代码*(p+1) = '1';,所以你试图替换e字符(在地址0x2468b)内文字"hello"1.您会得到分段违规(或其他一些未定义的行为),因为该文字字符串位于常量只读内存中(例如,可执行文件的文本段,至少在Linux上).

更好的代码可能是:

 #define MY_BUFFER_LEN 100
 char *p = malloc(MY_BUFFER_LEN);
 if (!p) { perror("malloc for p"); exit(EXIT_FAILURE); };
 strncpy(p, "hello", MY_BUFFER_LEN); /// you could do strcpy(p, "hello")
 *(p+1) = '1';
 printf("%s", p);
 free(p);
Run Code Online (Sandbox Code Playgroud)

并且如果你很幸运(没有内存故障),那么稍后会输出h1llo(输出只有在stdout被刷新时才会发生,因为它被缓冲,例如稍后调用fflush).所以不要忘记打电话

 fflush(NULL);
Run Code Online (Sandbox Code Playgroud)

在上一个代码块之后.阅读翻译(3),fflush(3).

一般建议是阅读您正在使用的每个函数的文档(甚至printf(3) ...).

关于printf和相关的函数,因为stdout通常是行缓冲的,实际上我强烈建议在代码中用\n-eg 结束每个格式控制字符串printf("%s\n", p);; 如果你不这样做(有些情况下你不想......)三思而后行,也许会评论你的代码.

不要忘记编译所有警告和调试信息(例如gcc -Wall -Wextra -g)然后学习如何使用调试器(例如gdb)


归档时间:

查看次数:

80 次

最近记录:

10 年,9 月 前