[英]Unix/C - 2 methods have different behaviour
我是UNIX C开发的初学者,需要一些帮助。 我有这两个功能:
void edit_char(){
int i;
int length = strlen(expression);
char *tmp = (char *) malloc((length+1)*sizeof(char));
pom[0]='*';
for(i=1;i<length+1;i++){
tmp[i] = expression[i-1];
}
strcpy(expression,tmp);
free((void *) tmp);
}
char *edit_char2(char *string){
int i;
int length = strlen(string);
char *tmp = (char *) malloc((length+1)*sizeof(char));
tmp[0]='/';
for(i=1;i<length+1;i++){
tmp[i] = string[i-1];
}
strcpy(string,tmp);
free((void *) tmp);
return string;
}
edit_char()编辑全局变量char *expression
- 它在开头放置一个符号“*”。 第二个edit_char2()执行几乎相同,但它不是编辑全局变量,而是从参数编辑字符串。
第一个函数工作正常,问题是第二个函数的tmp变量。 Malloc不返回大小为(length + 1)的空char数组。 它返回“xd \\ 372 \\ 267xd \\ 372 \\ 267 \\ 020”。
什么可能导致这个?
malloc只返回指向新分配的内存的指针,该内存不被视为“空”。 如果你想“清空”它 - 即用NULL填充你的memoy,你需要手动完成需要使用calloc
或手动填充它,例如:
编辑:另外我认为,因为你要为每个字符串添加一个字符,你不应该使用
newstring = malloc((strlen(string) + 1) * sizeof(char))
但反而
newstring = malloc((strlen(string) + 2) * sizeof(char))
为新字符和终止\\0
分配空间。
EDIT2:这也意味着你的功能无法正常工作/不安全 ! 您正在尝试使string
和expression
包含比最初可能分配的字符多1个字符!
tmp[0]='/';
for(i=1;i<length+1;i++){
tmp[i] = string[i-1];
}
您没有复制string
的尾随空字符。 这是strcpy(string,tmp);
所必需的strcpy(string,tmp);
请注意,您可以使用memmove
来执行复制而不是for
循环。 另请注意, malloc
的返回值的malloc
不是必需的,应该避免。 free
参数的演员也不是必需的。
如前所述,您的代码将无法正常工作。
在两个函数中使用strcpy(target, tmp)
时出现错误。 你需要明白,通过这样做,你几乎肯定会溢出target
指向的内存。 如果target只指向一个strlen(target + 1)
数组strlen(target + 1)
所有字符加上一个尾随的NULL),那么你正在复制tmp
的内容,也就是一个char
太短的内存数组。 为了说明这一点,运行如下的循环:
/* allocate two strings, containing copies
of constant string "Hello World" */
local_string = strdup("Hello World");
expression = strdup("Hello World");
for (i = 0; i < 100; i++) {
edit_char();
edit_char2(local_string);
printf("global_string after: [%s]\n", expression);
printf("local_string after: [%s]\n", local_string);
}
在第100次迭代之前,几乎总会导致程序异常终止。 在Debian Linux Squeeze上我得到了这个输出:
user@host$ ./a.out
global_string before: [Hello World]
local_string before: [Hello World]
global_string after: [*Hello World]
[...]
global_string after: [************Hello World]
local_string after: [////////////Hello World]
*** glibc detected *** ./a.out: double free or corruption (!prev): 0x00000000020e2050
你需要使用更多的指针魔法才能实现你想要的。 这是一个工作示例,设计改进限制代码重复:
user@host$ ./a.out
global_string before: [Hello World]
local_string before: [Hello World]
global_string after: [*Hello World]
local_string after: [/Hello World]
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char *global_string;
void add_one_leading_character(char leading, char **pointer_to_string)
{
char *new_string;
char *old_string;
/* old_string will hold the content of
pointer_to_string, for convenience */
old_string = *pointer_to_string;
/* allocate a new, empty string
(= filled with NULLs) holding enough space
for an additional character */
new_string = calloc(sizeof(*old_string), strlen(old_string) + 2);
/* new_string now holds the leading character,
followed by NULLs */
new_string[0] = leading;
/* concatenate the old_string to the new_string */
strcat(new_string, old_string);
/* make the pointer parameter points to the
address of new_string */
*pointer_to_string = new_string;
/* free the memory pointed by old_string */
free(old_string);
}
int main(int ac, char **av)
{
char *local_string;
/* allocate two strings, containing copies
of constant string "Hello World" */
local_string = strdup("Hello World");
global_string = strdup("Hello World");
printf("global_string before: [%s]\n", global_string);
printf("local_string before: [%s]\n", local_string);
/* add leading characters */
add_one_leading_character('/', &local_string);
add_one_leading_character('*', &global_string);
printf("global_string after: [%s]\n", global_string);
printf("local_string after: [%s]\n", local_string);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.