行为为wierd的malloced字符串的赋值
这是代码,是C代码。请解释=“string”的返回值 请注意行为为wierd的malloced字符串的赋值,c,C,这是代码,是C代码。请解释=“string”的返回值 请注意p=“hello”不复制任何字符串,只是将指针p设置为6字节文字字符串的地址“hello”。要复制字符串,请使用strncpy或strcpy(读取…),但要害怕 你也是 char * p = malloc(100); 它分配了一个能够容纳100字节的内存区域。让我们假设malloc成功(读取…),并返回了地址0x123456(通常,该具体地址在一次运行到下一次运行时是不可复制的,例如,由于) 然后分配p=“hello”所以您忘记了地
p=“hello”
不复制任何字符串,只是将指针p
设置为6字节文字字符串的地址“hello”
。要复制字符串,请使用strncpy
或strcpy
(读取…),但要害怕
你也是
char * p = malloc(100);
它分配了一个能够容纳100字节的内存区域。让我们假设malloc
成功(读取…),并返回了地址0x123456(通常,该具体地址在一次运行到下一次运行时是不可复制的,例如,由于)
然后分配p=“hello”
所以您忘记了地址0x123456(现在您有了a),您输入了6字节文本字符串的地址(假设它是0x2468a)
之后,机器执行*(p+1)=“1”的代码
因此,您试图将literal中的e
字符(地址0x2468b)替换为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);
如果幸运的话(没有内存故障),以后会输出h1llo
(只有当stdout
被刷新时,才会发生输出,因为它被刷新了,例如,通过稍后调用fflush
)。所以别忘了打电话
fflush(NULL);
在上一个代码块之后。读
一般建议是阅读您正在使用的每个函数(甚至…)
关于printf
和相关函数,由于stdout
通常是,在实践中,我强烈建议用\n
结束每个格式控制字符串-例如printf(“%s\n”,p)代码>在您的代码中;当您不这样做时(在某些情况下,您不想……),请三思而后行,并可能对代码进行注释
不要忘记使用所有警告和调试信息(例如,gcc-Wall-Wextra-g
)进行编译,然后学习如何使用调试器(例如,gdb
)您的代码不会做您认为它会做的事情
“hello”在幕后是指向六个字符的静态数组的指针,很可能是写保护的
当您将其分配给p时,malloc返回的指针将丢失,而p现在包含一个指向六个字符的静态数组的指针
p+1的分配可能会崩溃,也可能不会崩溃,但无论它做什么,它都是未定义的行为,并将导致故障
free(p)尝试释放六个字符的静态数组。那是行不通的。同样,未定义的行为,如果幸运的话,会立即崩溃 1)在C中,对malloc()的返回进行强制转换是不正确的(C++,可以强制转换)
2) 一旦分配了内存,将值分配给p
不是由=
完成的
strcpy(p,“你好”);更好。
3) 一旦分配正确,使用strcpy()
,*(p+1)='1'与p[1]='1'相同,并将导致“h1llo”
顺便说一下,在使用p=“hello”分配值hello(而不是strcpy()
)之后使用行*(p+1)=“1”将导致问题,如@gnasher、@Basile和其他人所述。几乎每一行都有问题:
1) 在第一行中,您将为p
分配新分配内存的地址。哪个是可以的
2) 在下一行中,您将使用某个静态字符串的地址覆盖它。这是不好的,因为分配的内存“丢失”,从而导致内存泄漏。
3) 在第三行中,您试图覆盖静态字符串位置中的某些内容,这可能是只读的,这是错误的
4) 在最后一行中,您试图释放字符串位置的内存,这是内存冲突。您需要了解指针是什么
在C语言中,没有可以存储字符串的变量。相反,字符串存储在字符数组中。为了能够处理这样的数组,可以使用一个变量(称为指针),该变量存储数组第一个元素的内存地址。此外,字符串有一个特殊的字符(nul字符)来指示它们的结束位置,但这在这里并不相关
在您发布的代码中,您分配内存来存储100个字符(通常为100字节),并获取指向该内存区域的第一个元素p(用于进一步读取:)的指针
无论何时使用字符串文字,都会分配一些内存并将其存储在该内存区域中。当您将其分配给p时,p现在指向新内存区域的第一个元素,该元素存储字符串(因此您丢失了分配给malloc->memory leak的内存)。现在,您尝试修改p指向的字符串。这不起作用,因为字符串文本存储为常量字符串。然后,你尝试释放这个字符串的内存,这是不可能的。所有这些错误都会产生运行时错误,并且不容易检测和修复。为了能够实现所需,请使用strcpy之类的函数将字符串从只读内存区域复制到指针:
strcpy(p, "string");
C中的字符串是数组,不能使用=给数组赋值,只能给数组的索引元素赋值。要复制字符串数据,请使用strcpy()
或strncpy()
。您的代码可能如下所示:
char *p = (char*) malloc(sizeof(char) * 100);
strcpy(p, "hello");
*(p+1) = '1';
printf("%s", p);
free(p);
试试看。不同之处在于p=“hello”
会将指针p设置为指向常量字符串“hello”,覆盖指向刚才分配的100字节内存块的指针。free(p)下面的代码>调用将失败,因为您正在传递分配函数未返回的指针,即使您使用的系统在尝试修改常量数据时未给出写入错误
如果确实需要将指针指向常量字符串(这种情况经常发生),请确保将指针声明为<
char *p = (char*) malloc(sizeof(char) * 100);
strcpy(p, "hello");
*(p+1) = '1';
printf("%s", p);
free(p);