0
int length = 12;
char *filename;
char *key;

filename = (char *)calloc(length, sizeof(char));
strcpy(filename, "Hello World");//filename = "Hello World\0";

现在我想从左边修剪 5 个字符

key = filename + 6;
*(filename + 5) = 0;

free(filename);

printf("%s\n", key);
printf("%s\n", filename); //No Segmentation Fault Why??

我可以使用 memcpy 或 strcpy 来实现这一点,但我可以通过上述方式做到这一点吗?

4

2 回答 2

4

这是错误的:

// So far so good...
filename = (char *)calloc(length, sizeof(char));
// No!!! You just leaked the previously allocated memory block!
// The `\0` at the end is also wrong.
filename = "Hello World\0";
// This is OK
key = filename + 6;
// You are writing into memory of a string literal, that's undefined behavior
*(filename + 5) = 0;
// You are freeing a string literal, that's undefined behavior too
free(filename);

至于没有段错误的部分,未定义的行为可能不会立即表现出来:例如,当您释放错误的区域时,释放本身可能会起作用,但随后的分配可能会失败。

如果您想缩短字符串,请复制并释放原始字符串:

char *filename = malloc(length);    // no cast
strcpy(filename, "Hello, world");   // no \0
char *trimmed = strdup(filename+6); // Make a copy
free(filename);                     // Free the original
filename = trimmed;                 // You are done!

通常,您只能释放已分配的内容。这样做的主要原因是malloc//将“簿记”信息calloc存储在与返回给您的地址相关联的内存中,通常在分配地址之前的一个块中。您可以尝试伪造它,但即使它有效,该解决方案也将是脆弱且不可移植的。realloc

于 2013-06-22T14:30:40.657 回答
0

即使您通过使用 strcpy() 或 strncpy() 将文件名初始化为“Hello World”来清理内存引导问题,您仍然会在最后一行出现 seg 错误,因为您正在释放之前分配的堆内存文件名 2 行以上。将你的 free() 移到最后,你会相对很好。

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

int main(int argc, char** argv)
{
    int length = 12;
    char *filename;
    char *key;

    filename = (char *)calloc(length, sizeof(char));
    strcpy(filename, "Hello World");
    key = filename + 6;
    *(filename + 5) = 0;

    printf("%s\n, key");
    printf("%s\n", filename); //No Segmentation Fault Why??

    free(filename);
}
于 2013-06-22T14:42:02.407 回答