【问题标题】:Why does strlen not work on mallocated memory?为什么 strlen 不适用于分配的内存?
【发布时间】:2015-10-28 18:40:47
【问题描述】:

我写了以下代码:

[all the required initialization]

printf("longueur de mid: %d\n",mid);
printf("longueur de n-mid: %d\n",n - mid);

L = (char*) malloc((mid)*sizeof(char)); 
R = (char*) malloc((n - mid)*sizeof(char)); 

printf("longueur de L: %d\n",strlen(L));
printf("longueur de R: %d\n",strlen(R));

[data treatment and free()]

使用printf 我得到了这个结果:

longueur de mid: 2
longueur de n-mid: 2
longueur de L: 3
longueur de R: 3

为什么输出不同?

【问题讨论】:

  • 您想了解 C-“字符串”到底是什么,因为 C 中没有数据类型“字符串”。
  • 如果你用null-characters(零)初始化,你会看到区别。即L = calloc(mid, sizeof(char));R = calloc((n - mid), sizeof(char));注意:为了存储mid的字符串,你必须分配mid + 1为空终止字符提供空间)
  • 你已经分配了内存,但是你什么也没放。所以它的内容是随机的,并且可能有任何字符串长度。

标签: c malloc strlen


【解决方案1】:

strlen 迭代直到找到一个空字节。 malloc 未初始化分配的空间,因此可能会随机出现空字节。毕竟,由于访问了未初始化的内存,这是未定义的行为。

单独确定mallocated 块的大小是不可能的。将大小存储在单独的变量中,例如 LsizeRsize


注意事项:

  • don't cast the result of malloc
  • 乘以sizeof(char) 是多余的,因为sizeof(char) == 1
  • malloc 之后使用free
  • size_t 的相应格式说明符,又名“strlensizeof 运算符的返回类型”是%zu%d 用于ints1

1 正如@chux 在该答案的 cmets 中指出的那样

【讨论】:

  • sizeof(char) 是没有意义的,但sizeof(L) 不是,因为即使L 的类型更改为wchar_t 之类的其他内容,它也能正常工作。类型名称几乎不应该传递给sizeof
  • 对一个好答案的建议注释:printf("longueur de L: %d\n",strlen(L)); 是 UB - 应该是 %zustrlen() 返回一个 size_t,就像 malloc(size_t n) 采用的类型一样。
  • 感谢您的澄清。我不认为问题是由非初始化引起的。即使我使用数据,也会发生这个问题。例如,当我保留 2 * sizeof(char) 时,字符串中总是有第三个字符。或者,正确的做法是使用 NULL 对其进行初始化。
  • @White Uhm,是的,问题由访问未初始化的内存引起的,正如我和另一个答案的创建者提到的那样。这是未定义的行为。随机性在起作用(从 C 标准的角度来看)。
【解决方案2】:

正如有人部分提到的,strlen() 将输入的输入转换为正确的内存位置,然后该位置增加 1,直到找到空字符。尝试对来自 malloc() 调用的指针使用 strlen() 的问题在于,返回指针处返回的数据可以是任何内容,具体取决于您的操作系统如何处理内存。

如果您希望您的指针在分配内存时引用一组有保证的空字符,您可以使用以下代码:

L = calloc(1,mid+1); 
R = calloc(1,n - mid+1); 

那么至少当你使用 strlen() 时,你会得到一个零。

如果你必须使用 malloc(),那么你可以使用这个代码:

L = malloc(1,mid+1); 
R = malloc(1,n - mid+1); 
memset(L,0,mid);
memset(R,0,n - mid);

在这两段代码中,我假设 L 和 R 被声明为 char*

并且绝对在使用 calloc 和 malloc 分配的所有内存上使用 free(),否则您可能会出现内存泄漏,这可能会导致您重新启动计算机。

如果你想在内存中快速放入固定数量的字节,在分配内存后使用:

memset(L,x,mid);
memset(R,x,n - mid);

但将 x 更改为除零以外的任何值,否则它将为空。

这是一个示例程序,它的功能更像您的预期:

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


int main(){
  int size=10;
  char* a=calloc(1,100); // allocate 100 null's and store pointer to them at 'a'
  printf("%d \n",size); // print wanted size
  printf("%d \n",strlen(a)); // print length of memory space which = 0
  memset(a,'A',size); // put 10 A's at the beginning of allocated memory
  printf("%d \n",strlen(a)); // print length again which now = 10
  printf("%s \n",a); // print memory (which is 10 A's)
  free(a); // free the memory
  return 0; 
}

即使启用了编译器选项-Wall-Wextra,上述代码在我的编译器中编译良好,也没有任何警告。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-16
    • 2015-02-22
    • 2012-01-14
    • 2014-01-11
    • 1970-01-01
    • 1970-01-01
    • 2013-03-17
    相关资源
    最近更新 更多