C 无法确定分配内存的正确算法

C 无法确定分配内存的正确算法,c,segmentation-fault,dynamic-memory-allocation,dynamic-arrays,C,Segmentation Fault,Dynamic Memory Allocation,Dynamic Arrays,我有一段代码,我正在用C编写一个动态数组。所以这里的主要问题是,假设你把值1加到数组中,然后你决定把值5加到数组中。在我的例子中,当你试图打印索引0时,它假设为1,它给了我一个seg错误。但是当你打印索引1时,它给了我5,这是正确的值。由于某种原因,它会忘记除当前值之外的所有先前的附加值。我已经做了valgrind检查,我将在显示文件后显示结果: 顶点h: #ifndef _VERTEX_AM_H_LB #define _VERTEX_AM_H_LB 1 #pragma once #includ

我有一段代码,我正在用C编写一个动态数组。所以这里的主要问题是,假设你把值1加到数组中,然后你决定把值5加到数组中。在我的例子中,当你试图打印索引0时,它假设为1,它给了我一个seg错误。但是当你打印索引1时,它给了我5,这是正确的值。由于某种原因,它会忘记除当前值之外的所有先前的附加值。我已经做了valgrind检查,我将在显示文件后显示结果:

顶点h:

#ifndef _VERTEX_AM_H_LB
#define _VERTEX_AM_H_LB 1
#pragma once
#include<stdint.h>
/**
 * Vertex Library C
 *
 * GCC C99 <Vertex.h>
 *
 * @author Amanuel Bogale
 * @copyright 2016 Amanuel Bogale
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 *
 */

//@union for storing
//data types supported
//for vertex
typedef union
    {
        char ch; //1 byte
        unsigned char uch;//1 byte
        signed char sch;// 1 byte
        int in;//2 or 4bytes
        unsigned int uin;//2 or 4bytes
        long ln;// 4byte
        unsigned long uln; //4byte
        long long lnln; //8byte
        short sh;// 2byte
        unsigned short ush; //2bytes
        float fl;//4byte
        double db; //8byte
        long double ldb; //10byte
}type;

/*
 * @struct for defining
 * vertex. Initalize First
 */
struct vertex_am
{
    size_t current_size;
    type type;
    long long size_contents;
    void **contents; //Array Of Void Pointers
    //Add to the end of array
    void (*add)(struct vertex_am *self,void*val);
};

typedef struct vertex_am vertex_am;



vertex_am* init_vertex(size_t size, vertex_am* vertex);
void end_vertex(vertex_am* vertex);
long long get_elements_num(vertex_am vert);
void add_end(vertex_am *vert, void* val);
void* get_val(vertex_am vert,long long index);
int get_first_index(vertex_am vert, void*key);
int get_last_index(vertex_am vert, void*key);
#endif
因为在main.c中可以看到添加了三项。。。第二个指数是最新的。如果我尝试打印索引1或0,它将给出一个分段错误,出于某种原因。。。就像我说的,我做了一个valgrind检查,我得到了这个:

==37900== Memcheck, a memory error detector
==37900== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==37900== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==37900== Command: ./main
==37900== 
==37900== Invalid write of size 8
==37900==    at 0x4008A1: add_end (Vertex.c:34)
==37900==    by 0x400747: main (main.c:17)
==37900==  Address 0x5420170 is 0 bytes after a block of size 16 alloc'd
==37900==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==37900==    by 0x40087A: add_end (Vertex.c:32)
==37900==    by 0x400747: main (main.c:17)
==37900== 
==37900== Invalid read of size 8
==37900==    at 0x400750: main (main.c:23)
==37900==  Address 0x5420170 is 0 bytes after a block of size 16 alloc'd
==37900==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==37900==    by 0x40087A: add_end (Vertex.c:32)
==37900==    by 0x400747: main (main.c:17)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x400900: get_first_index (Vertex.c:48)
==37900==    by 0x400795: main (main.c:27)
==37900== 
==37900== Invalid read of size 8
==37900==    at 0x4008F9: get_first_index (Vertex.c:48)
==37900==    by 0x400795: main (main.c:27)
==37900==  Address 0x5420170 is 0 bytes after a block of size 16 alloc'd
==37900==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==37900==    by 0x40087A: add_end (Vertex.c:32)
==37900==    by 0x400747: main (main.c:17)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4B43: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Use of uninitialised value of size 8
==37900==    at 0x50A172B: _itoa_word (_itoa.c:179)
==37900==    by 0x50A50EC: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A1735: _itoa_word (_itoa.c:179)
==37900==    by 0x50A50EC: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A516F: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4C19: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A53DA: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4C6B: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4CA2: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
44First Index : 44 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x40094B: get_last_index (Vertex.c:62)
==37900==    by 0x4007D7: main (main.c:30)
==37900== 
==37900== Invalid read of size 8
==37900==    at 0x400944: get_last_index (Vertex.c:62)
==37900==    by 0x4007D7: main (main.c:30)
==37900==  Address 0x5420170 is 0 bytes after a block of size 16 alloc'd
==37900==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==37900==    by 0x40087A: add_end (Vertex.c:32)
==37900==    by 0x400747: main (main.c:17)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4B43: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Use of uninitialised value of size 8
==37900==    at 0x50A172B: _itoa_word (_itoa.c:179)
==37900==    by 0x50A50EC: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A1735: _itoa_word (_itoa.c:179)
==37900==    by 0x50A50EC: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A516F: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4C19: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A53DA: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4C6B: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4CA2: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
Last Index : 44 
==37900== 
==37900== HEAP SUMMARY:
==37900==     in use at exit: 48 bytes in 3 blocks
==37900==   total heap usage: 5 allocs, 2 frees, 1,136 bytes allocated
==37900== 
==37900== LEAK SUMMARY:
==37900==    definitely lost: 48 bytes in 3 blocks
==37900==    indirectly lost: 0 bytes in 0 blocks
==37900==      possibly lost: 0 bytes in 0 blocks
==37900==    still reachable: 0 bytes in 0 blocks
==37900==         suppressed: 0 bytes in 0 blocks
==37900== Rerun with --leak-check=full to see details of leaked memory
==37900== 
==37900== For counts of detected and suppressed errors, rerun with: -v
==37900== Use --track-origins=yes to see where uninitialised values come from
==37900== ERROR SUMMARY: 30 errors from 22 contexts (suppressed: 0 from 0)
amanuel@ubuntu:~/Code/E-Workspace/CustLibs$ 
针对Vertex.c中的add函数的许多无效写入:

void add_end(vertex_am *vert, void* val)
{
    vert->contents = (void **)malloc(sizeof(vert->contents) + (sizeof(val)) );
//  vert->contents = (void **)malloc(sizeof(void)*(vert->size_contents+1));
    vert->contents[vert->size_contents] = val;
    vert->size_contents++;
}

。这是我现在掌握的关于这个问题的很多信息,如能一如既往地提供帮助,我将不胜感激。

在调用
malloc
时使用的表达式
sizeof(vert->contents)+(sizeof(val))
将无法按预期工作。它将为两个指针分配空间,仅此而已。无论要为多少个条目分配内存,都只能获得8或16个字节(取决于您是在32位还是64位平台上)

我猜您应该分配
sizeof(*vert->contents)*(vert->size\u contents+1)
字节


还有另一个问题:每次调用
add_end
时,您都会分配一个新的内存块,完全忽略旧内存,并且在进行上述更改后,会出现内存泄漏,以及大量未初始化的内存

如果你想重新分配内存,你应该使用它。如果正确初始化指向
NULL
的指针,甚至可以将其用于初始分配

所以代码应该是

void **temp = realloc(vert->contents, sizeof(*vert->contents) * (vert->size_contents+1));
if (temp == NULL)
{
    // TODO: Handle error
}
else
{
    vert->contents = temp;
    // Rest of your code...
}

在第一次调用
realloc
之前,将
vert->contents
初始化为
NULL
,否则您将有未定义的行为。

您可能希望
realloc
()
vert->contents
在分配
vert->contents>之前使用
size\u contents+1
size[vert->size\u contents]=val
@Dsafds不,我不知道,星号(“星”)应该在那里。它将给出与
sizeof(void*)
相同的结果(也请注意那里的星号),但如果您更改
vert->contents
的类型,则更安全。将其更改为
vert->contents=(void**)realloc(vert,sizeof(*vert->contents)*(vert->size_contents+1));
就像你建议的那样。我在valgrind(11)中得到的错误少了很多。但是现在,即使是最新的索引也出现了seg错误。(我不是要删除commet对不起……没有看到你的响应)。我的代码基本上和以前一样,除了上面列出的更改,你知道吗sugested@Dsafds几乎是对的,但是你的指针(re)分配是
vert->contents
,而不是
vert
。记住
vert->contents
在第一次调用时必须是空指针。另外,不要重新分配回您正在重新分配的指针,如果
realloc
返回
null
,您将丢失原始指针并导致内存泄漏。非常感谢Joachim!!!(抱歉等待,不得不吃点东西)只有一个问题,这与Orignal(抱歉)没有太大关系。你可以看到,每当我必须调用函数add_end()来在末尾添加。但是有没有办法让我通过结构的实例来调用它?像do一样,vertex_am vert;。然后是vert.add_end()?@Dsafds如果您将一个成员添加到指向函数的指针结构中,并对其进行初始化,使其指向真正的
add\u end
函数,则可以,但不可以。也许您想?
==37900== Memcheck, a memory error detector
==37900== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==37900== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==37900== Command: ./main
==37900== 
==37900== Invalid write of size 8
==37900==    at 0x4008A1: add_end (Vertex.c:34)
==37900==    by 0x400747: main (main.c:17)
==37900==  Address 0x5420170 is 0 bytes after a block of size 16 alloc'd
==37900==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==37900==    by 0x40087A: add_end (Vertex.c:32)
==37900==    by 0x400747: main (main.c:17)
==37900== 
==37900== Invalid read of size 8
==37900==    at 0x400750: main (main.c:23)
==37900==  Address 0x5420170 is 0 bytes after a block of size 16 alloc'd
==37900==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==37900==    by 0x40087A: add_end (Vertex.c:32)
==37900==    by 0x400747: main (main.c:17)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x400900: get_first_index (Vertex.c:48)
==37900==    by 0x400795: main (main.c:27)
==37900== 
==37900== Invalid read of size 8
==37900==    at 0x4008F9: get_first_index (Vertex.c:48)
==37900==    by 0x400795: main (main.c:27)
==37900==  Address 0x5420170 is 0 bytes after a block of size 16 alloc'd
==37900==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==37900==    by 0x40087A: add_end (Vertex.c:32)
==37900==    by 0x400747: main (main.c:17)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4B43: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Use of uninitialised value of size 8
==37900==    at 0x50A172B: _itoa_word (_itoa.c:179)
==37900==    by 0x50A50EC: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A1735: _itoa_word (_itoa.c:179)
==37900==    by 0x50A50EC: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A516F: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4C19: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A53DA: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4C6B: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4CA2: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007B0: main (main.c:28)
==37900== 
44First Index : 44 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x40094B: get_last_index (Vertex.c:62)
==37900==    by 0x4007D7: main (main.c:30)
==37900== 
==37900== Invalid read of size 8
==37900==    at 0x400944: get_last_index (Vertex.c:62)
==37900==    by 0x4007D7: main (main.c:30)
==37900==  Address 0x5420170 is 0 bytes after a block of size 16 alloc'd
==37900==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==37900==    by 0x40087A: add_end (Vertex.c:32)
==37900==    by 0x400747: main (main.c:17)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4B43: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Use of uninitialised value of size 8
==37900==    at 0x50A172B: _itoa_word (_itoa.c:179)
==37900==    by 0x50A50EC: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A1735: _itoa_word (_itoa.c:179)
==37900==    by 0x50A50EC: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A516F: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4C19: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A53DA: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4C6B: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
==37900== Conditional jump or move depends on uninitialised value(s)
==37900==    at 0x50A4CA2: vfprintf (vfprintf.c:1631)
==37900==    by 0x50AC848: printf (printf.c:33)
==37900==    by 0x4007F2: main (main.c:31)
==37900== 
Last Index : 44 
==37900== 
==37900== HEAP SUMMARY:
==37900==     in use at exit: 48 bytes in 3 blocks
==37900==   total heap usage: 5 allocs, 2 frees, 1,136 bytes allocated
==37900== 
==37900== LEAK SUMMARY:
==37900==    definitely lost: 48 bytes in 3 blocks
==37900==    indirectly lost: 0 bytes in 0 blocks
==37900==      possibly lost: 0 bytes in 0 blocks
==37900==    still reachable: 0 bytes in 0 blocks
==37900==         suppressed: 0 bytes in 0 blocks
==37900== Rerun with --leak-check=full to see details of leaked memory
==37900== 
==37900== For counts of detected and suppressed errors, rerun with: -v
==37900== Use --track-origins=yes to see where uninitialised values come from
==37900== ERROR SUMMARY: 30 errors from 22 contexts (suppressed: 0 from 0)
amanuel@ubuntu:~/Code/E-Workspace/CustLibs$ 
void add_end(vertex_am *vert, void* val)
{
    vert->contents = (void **)malloc(sizeof(vert->contents) + (sizeof(val)) );
//  vert->contents = (void **)malloc(sizeof(void)*(vert->size_contents+1));
    vert->contents[vert->size_contents] = val;
    vert->size_contents++;
}
void **temp = realloc(vert->contents, sizeof(*vert->contents) * (vert->size_contents+1));
if (temp == NULL)
{
    // TODO: Handle error
}
else
{
    vert->contents = temp;
    // Rest of your code...
}