需要有关malloc

时间:2019-04-13 10:43:12

标签: c

我不知道当我为5分配内存时它会打印出OneExample。 我知道可以使用strncpy做到这一点 但是有没有办法不用strncpy

它可以与strncpy一起使用,但是有没有办法在没有strncpy的情况下做到这一点?

void main()
{

    char *a;

    a=(char*)malloc(5);

    a="OneExample";
    printf("%s",a);

    free(a);

}

它打印出OneExample

是否应打印OneE? 有人可以解释吗?

void main()
{

    char *a;

    a=(char*)malloc(5);

    a="OneExample";
    printf("%s",a);

    free(a);

}

7 个答案:

答案 0 :(得分:4)

您没有在使用分配的内存。分配内存后,使用指向字符串文字的指针覆盖指针a,从而导致内存泄漏。后续对free的调用也可能会使您的应用程序崩溃,因为您是在未分配free的指针上调用malloc

如果要使用分配的空间,可以将其复制到其中(例如,使用strncpy)。

答案 1 :(得分:2)

  

我不知道当我为5分配内存时它会打印出OneExample。我知道可以使用strncpy来做到这一点,但是有没有办法不用strncpy来做到这一点

     

它可以与strncpy一起使用,但是有没有办法在没有strncpy的情况下做到这一点?

您可以使用memcpy()作为替代。
阅读memcpy()并检查this

似乎您对C语言中的指针有误解。
查看代码的这一部分:

    a=(char*)malloc(5);

    a="OneExample";
    printf("%s",a);

    free(a);

您正在将内存分配给char指针a,然后立即将其指向字符串文字OneExample

这是代码中的内存泄漏,因为您丢失了分配的内存的引用。

您应该注意free()会释放先前由malloc()calloc()realloc()分配的空间,否则行为是不确定的。
在您的程序中,您尝试释放字符串文字"OneExample"的内存,这将导致未定义的行为。

使用memcpy(),您可以执行以下操作:

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

int main (void) {
    char *a = malloc(5);

    if (a == NULL) {
        fprintf (stderr, "Failed to allocate memory\n");
        exit(EXIT_FAILURE);
    }

    memcpy (a, "OneExample", 4);   // copy 4 characters to a, leaving space for null terminating character

    a[4] = '\0';      // make sure to add null terminating character at the end of string

    printf("%s\n",a);

    free(a);

    return 0;
}

其他:

  • 使用void作为main函数的返回类型不符合标准。主函数的返回类型应为int

  • 遵循良好的编程习惯,请始终检查malloc返回。

  • Do not cast the malloc return

答案 2 :(得分:2)

  • 要使用malloc,您需要#include <stdlib.h>(未在代码中显示)。原因是malloc具有返回void *的原型,而没有该原型,则编译器将假定其返回int。在64位体系结构中,这是个问题,因为void *是64位类型,而int是32位。这使得提取malloc()返回的值的代码仅占用结果的32个少显着位,然后将它们转换为指针(按照您的类型转换,您不应该- -对此有很多评论-,您将避免应该尝试将int值转换为char *而无需强制转换的错误)
  • 在将malloc(3)给定的指针分配给a之后,用字符串文字"OneExample"的地址覆盖该指针。这有两件事:

    • 首先,您丢失了malloc(3)给定的指针值,该指针值存储在a中,因此您将不再拥有它,并且将永远无法free(3) 。这称为内存泄漏,您应避免这些,因为它们是编程错误。
    • 这将在对free(3)的调用中做出某种未定义的行为,该行为仅接受malloc先前返回的指针值作为参数(并且这不是存储在{{1中的实际地址) }})可能您遇到了a个中断,并且此调用导致程序崩溃。

当您对SIGSEGV进行分配时,您只是在更改存储在其中的指针值,而不是更改延迟的内存内容,因此调用a才有意义,因为这是唯一的方法是在周围复制字符串。或者,您可以一一复制字符,如下所示:

strcpy(3)

最后一步是什么使得有必要在char *a = malloc(5); /* this makes a memory buffer of 5 char available through a */ int i; for(i = 0; i < 4 /* see below */; i++) a[i] = "OneExample"[i]; /* this is the copy of the char at pos i */ a[i] = '\0'; /* we must terminate the string if we want to print it */ 而不是for时运行i < 4循环,因为我们要求i < 5输入五个字符,并且必须包含字符串终止符char。

有一个标准库可供选择,它是:

malloc()

等效于:

char *a = strdup("OneExample");

但是如果您想通过将字符串截断为5来解决示例,则可以执行以下操作:

#define S "OneExample"
char *a = malloc(strlen(S) + 1); /* see the +1 to allow for the null terminator */
strcpy(a, S);

,您可以将其称为:

char *dup_truncated_at(const char *s, int at)
{
    char *result = malloc(at + 1); /* the size we need */
    memcpy(result, s, at); /* copy the first at chars to the position returned by malloc() */
    result[at] = '\0';  /* and put the string terminator */
    return result; /* return the pointer, that must be freed with free() */
}

答案 3 :(得分:0)

首先在这里

if(isset($_POST['attended'])) {
....
}

if(isset($_POST['attended2'])) {
...
}

您已经从堆中立即分配了a=(char*)malloc(5); 个字节的内存

5

使用字符串文字a="OneExample"; 的基地址覆盖以前的动态内存,原因是"OneExample"不再指向任何动态内存,它会导致内存泄漏(因为没有对象指向动态内存,它丢失了),甚至在那之后

a

释放非动态分配的内存会导致不确定的行为

旁注,请务必阅读Why does malloc allocate more memory spaces than I ask forMalloc vs custom allocator: Malloc has a lot of overhead. Why?以获得有关free(a); 的更多信息。

答案 4 :(得分:0)

您需要清楚指针所指向的内容。首先,您声明一个char *a;。这是指向字符的指针。

a=(char*)malloc(5);行中,您用malloc分配了一点内存,并将该内存的位置分配给指针a。 (有点口语,但您明白我的意思)。因此,a现在指向5个字节的新分配内存。

接下来,a="OneExample";a得到一个新值,即字符串OneExample的位置;现在不再有指向分配的五个字节的指针。他们现在是孤儿。 a指向静态上下文中的字符串。根据体系结构,编译器和许多其他事物,这可能是静态数据空间,程序空间或类似的东西。至少不是用于变量的内存的一部分。

因此,当您执行printf("%s",a);时,a指向字符串,而printf将打印出字符串(完整的字符串)。

当您执行free(a);时,您试图释放程序,数据等空间的一部分。也就是说,通常是不允许的。您应该收到一条错误消息;在Linux中将是这样的:

*** Error in `./try': free(): invalid pointer: 0x000000000040081c ***
======= Backtrace: =========
/lib64/libc.so.6(+0x776f4)[0x7f915c1ca6f4]
/lib64/libc.so.6(+0x7ff4a)[0x7f915c1d2f4a]
/lib64/libc.so.6(cfree+0x4c)[0x7f915c1d6c1c]
./try[0x400740]
/lib64/libc.so.6(__libc_start_main+0xf0)[0x7f915c1737d0]
./try[0x4005c9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 21763273                           /home/ljm/src/try
00600000-00601000 r--p 00000000 08:01 21763273                           /home/ljm/src/try
00601000-00602000 rw-p 00001000 08:01 21763273                           /home/ljm/src/try
[- more lines -]

答案 5 :(得分:0)

语句a="OneExample";并不意味着“将字符串"OneExample"复制到a中。”

在C语言中,像"OneExample"这样的字符串文字是编译器为您分配的char数组。在表达式中使用该数组时,该数组将自动成为指向其第一个元素的指针。 1

所以a="OneExample"的意思是“将指针a设置为指向char中的第一个"OneExample"。”

现在,a指向字符串,printf当然会打印它。

然后free(a)是错误的,因为它试图释放"OneExample"的内存,而不是释放提供的malloc的内存。

脚注

1 当字符串文字是sizeof的操作数,一元&的操作数或用于初始化数组时,不会发生此自动转换。

答案 6 :(得分:0)

=不会复制字符串,只是将新值分配给覆盖旧值的指针。您需要分配足够的内存来存储字符串,然后将其复制到分配的空间中

#define MYTEXT "This string will be copied"

char *a = malloc(strlen(MYTEXT) + 1);  //+1 because you need to store the trailing zero
strcpy(a,MYTEXT);

然后您可以在不再需要的时候释放a