C免费malloc&#d结构成员和结构

时间:2013-06-06 01:22:34

标签: c struct malloc free

当我运行尝试释放此结构中的任何内容时,我遇到了问题。首先是标题中的结构定义:

    typedef struct{
int* rType;
unsigned long int numCols;
char* rString;  //The literal string, NULL delimited
int rsSize;     //The size of the string, since NULLS can't be used to find the string end
int* colsIndex; //Where each new column starts in rString
long* iColVals;   //integer version of the column
double* dColVals; //double precision value of column
}  row_t ;

然后在这里可以创建结构的实例:

row_t* delimitLine(char* line, char* delimList, char delimListSize)
{
row_t* thisRow;
.
.
.
//Make a place for this stuff in memory
thisRow = (row_t*) malloc(sizeof(row_t));
if(thisRow==NULL) return NULL;
.
.
.
thisRow->rString = line;

//Make Row Mem

    //colsIndex
    thisRow->colsIndex = (int*) malloc(numCols*sizeof(int));
    if(thisRow->colsIndex==NULL) return NULL;   

    //rType
    thisRow->rType = (int*) malloc(numCols*sizeof(int));
    if(thisRow->rType==NULL) return NULL;   

    //iColVals
    thisRow->iColVals = (long*) malloc(numCols*sizeof(long));
    if(thisRow->iColVals==NULL) return NULL;    

    //dColVals
    thisRow->dColVals = (double*) malloc(numCols*sizeof(double));   
    if(thisRow->dColVals==NULL) return NULL;    
.
.
.
return thisRow;

然后是“行”的创建方式:

char* RBreadLine(fifo_t* fifo)
{
char* outbuf = NULL;
.
.
.
outbuf = (char*) malloc(sizeof(char)*(cnt+1));
.
.
.
return outbuf;
}

最后调用序列:

main()
{
row_t* row = NULL;
.
.
.
while(kg>=0)
{
//test condition to exit loop not shown
line = RBreadLine(fifo);
.
.
.

 row = delimitLine(line, delimList, delimListSize);
//some code to manipulate the row data here
 printRow(row);
 rowDestructor(row);



}

}

当我注释掉对rowDestructor的调用时,程序按预期运行,但如果我尝试释放任何内容,则会崩溃。我已经尝试评论除了struct的单个成员之外的所有行,但仍然会崩溃,所以我在这里做错了。

我们的想法是拥有一个大型文本文件处理程序,该程序逐行读取并允许我操作行数据,然后printRow()输出最终结果。

简单的测试用例是只输出delimitLine函数中的值(它只分配内存并用数据填充行结构)。

当这个过程结束时,我应该释放内存并重新开始。如果我不调用析构函数,那么这个程序按预期工作,而是每次有一个对RBreadLine()和delimitLine()的新调用时,只需复制这些指针。

如果我调用rowDestructor(),那么程序在第一行之后崩溃(在第一次调用rowDestructor()时):

 Now to start outputting line
    1)  2)  3)  4)  5)  6)  7)  8)  9)  10)  (-10)63.116722551236001948     0       0       0       0       1       1       1       1       1       0    1

    Aborted (core dumped)

也许我对malloc()或free()有一些我不了解的东西,但似乎我可以从结构成员访问有效数据而没有错误并且不会导致崩溃,那么free应该可以释放记忆已被malloc'd。

也许我只是通过传递这些指针来做坏事(比如将指针传递给“line”指向一个将它分配给struct成员的函数)但是在我看来它们都很好。我知道结构的每个成员都获得malloc,因此我应该能够释放所有这些,因为我向上工作然后释放结构。然后我可以将另一个指针转储到行结构上并再次执行它。

我这样做的原因是因为我希望能够处理非常大的数据集。这是一个程序的结构重写,曾经用fread将它全部加载到内存中,然后处理它,但是我的一些数据集会导致计算机耗尽内存......所以我将采用块处理方法

一旦我可以成功释放一行,那么我可以通过创建一个row_t **来构建它,我可以使用FIFO缓冲区概念将行循环到row_t **上,这样我就可以查找文本文件向前和向后合理的数量(比如应用FIR滤波器),但不需要将整个文件加载到内存中。

例如,行FIFO会将这些新的row_t *结构存储到row_t **上,然后在填充循环缓冲区并开始覆盖旧指针后释放旧的结构...这就是我要去的地方此

我认为对这个问题的回答将是我对malloc()和free()的理解上的一个突破,或者可能对指针和结构有所了解。

感谢您的任何意见。

编辑: 我为忽略我问题中最重要的部分而道歉:

void rowDestructor(row_t* thisRow)
{
    //rString
    free(thisRow->rString);

    //colsIndex
    free(thisRow->colsIndex);   

    //rType
    free(thisRow->rType);   

    //iColVals
    free(thisRow->iColVals);    

    //dColVals
    free(thisRow->dColVals);

    //finally kill the whole thing
    free(thisRow);
}

而且,由于其他人提到了编译器标志,这就是我正在使用的:

gcc  -Wall laproc.c utils.c csvsurgeon.c -lm -o csv-surgeon

(laproc.c是我需要与math lib链接的特定信号处理代码,在本例中我将其简化为不调用这些函数的地方)

我正在使用此版本的gcc:

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-pc-cygwin/4.5.3/lto-wrapper.exe
Target: i686-pc-cygwin
Configured with: /gnu/gcc/releases/respins/4.5.3-3/gcc4-4.5.3-3/src/gcc-4.5.3/configure --srcdir=/gnu/gcc/releases/respins/4.5.3-3/gcc4-4.5.3-3/src/gc
c-4.5.3 --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --libexecdir=/usr/lib --datadir=/usr/share --localstatedir=/var --sysco
nfdir=/etc --datarootdir=/usr/share --docdir=/usr/share/doc/gcc4 -C --datadir=/usr/share --infodir=/usr/share/info --mandir=/usr/share/man -v --with-g
mp=/usr --with-mpfr=/usr --enable-bootstrap --enable-version-specific-runtime-libs --libexecdir=/usr/lib --enable-static --enable-shared --enable-shar
ed-libgcc --disable-__cxa_atexit --with-gnu-ld --with-gnu-as --with-dwarf2 --disable-sjlj-exceptions --enable-languages=ada,c,c++,fortran,java,lto,obj
c,obj-c++ --enable-graphite --enable-lto --enable-java-awt=gtk --disable-symvers --enable-libjava --program-suffix=-4 --enable-libgomp --enable-libssp
 --enable-libada --enable-threads=posix --with-arch=i686 --with-tune=generic --enable-libgcj-sublibs CC=gcc-4 CXX=g++-4 CC_FOR_TARGET=gcc-4 CXX_FOR_TA
RGET=g++-4 GNATMAKE_FOR_TARGET=gnatmake GNATBIND_FOR_TARGET=gnatbind --with-ecj-jar=/usr/share/java/ecj.jar
Thread model: posix
gcc version 4.5.3 (GCC)

也许那就是我的问题...... 我用其他gcc版本重新编译了:

Using built-in specs.
COLLECT_GCC=C:\Program Files\CodeBlocks\MinGW-newer\bin\gcc.exe
COLLECT_LTO_WRAPPER=c:/program files/codeblocks/mingw-newer/bin/../libexec/gcc/mingw32/4.5.2/lto-wrapper.exe
Target: mingw32
Configured with: ../../src/gcc-4.5.2/configure --build=mingw32 --enable-languages=c,c++,ada,fortran,objc,obj-c++ --enable-threads=win32 --enable-libgo
mp --enable-lto --enable-fully-dynamic-string --enable-libstdcxx-debug --enable-version-specific-runtime-libs --with-gnu-ld --disable-nls --disable-wi
n32-registry --disable-symvers --disable-werror --prefix=/mingw32tdm --with-local-prefix=/mingw32tdm --enable-cxx-flags='-fno-function-sections -fno-d
ata-sections' --with-pkgversion=tdm-1 --enable-sjlj-exceptions --with-bugurl=http://tdm-gcc.tdragon.net/bugs
Thread model: win32
gcc version 4.5.2 (tdm-1)

另一个版本

Using built-in specs.
Target: mingw32
Configured with: ../../gcc-4.4.1/configure --prefix=/mingw --build=mingw32 --enable-languages=c,ada,c++,fortran,objc,obj-c++ --disable-nls --disable-w
in32-registry --enable-libgomp --enable-cxx-flags='-fno-function-sections -fno-data-sections' --disable-werror --enable-threads --disable-symvers --en
able-version-specific-runtime-libs --enable-fully-dynamic-string --with-pkgversion='TDM-2 mingw32' --enable-sjlj-exceptions --with-bugurl=http://www.t
dragon.net/recentgcc/bugs.php
Thread model: win32
gcc version 4.4.1 (TDM-2 mingw32)

对于4.4.1版本,它将在运行中的不同点处发生故障。在一对夫妇运行它甚至没有seg错误一次通过它,所以也许我有一个编译器问题。因为我有cygwin,也许编译器是混合实用程序和链接器(使用“/ bin”的错误目录)。

我希望我已经包含了足够的内容,以清楚我现在正在使用这些malloc'd指针做什么,因为我已经包含了rowDestructor()代码。感谢您的评论到目前为止。

如果我的C实现本身有任何问题,我想解决它。与此同时,我将清理我的开发环境,看看我是否可以通过确保所有组件的正确路径来获得更好的结果。

1 个答案:

答案 0 :(得分:3)

事实证明我的记忆管理很好(难怪我把头发拉了出来)。我在Linux上编译了这个程序,并在分配内存时很快发现了“一个接一个”的错误,因此我访问了一些超出范围的内存。程序故障立即出现在Linux机器上,而Windows会让程序运行一段时间再终止它。

问题出在哪里,对于那些感兴趣的人:

 row_t* delimitLine(char* line, char* delimList, char delimListSize)
{
//<Analyze "line" to count number of data fields>
.
.
.

这就是它的完成方式:

//Populate Row Data 
thisRow->numCols = numCols+1;   

这是如何解决的:

//Populate Row Data 
numCols+=1;
thisRow->numCols = numCols; 

这里有一个关于为什么这是一个问题的提示

.
.
.
    //colsIndex
    thisRow->colsIndex = (int*) malloc(numCols*sizeof(int));
    if(thisRow->colsIndex==NULL) return NULL;   

    //rType
    thisRow->rType = (int*) malloc(numCols*sizeof(int));
    if(thisRow->rType==NULL) return NULL;   

    //iColVals
    thisRow->iColVals = (long*) malloc(numCols*sizeof(long));
    if(thisRow->iColVals==NULL) return NULL;    

    //dColVals
    thisRow->dColVals = (double*) malloc(numCols*sizeof(double));   
    if(thisRow->dColVals==NULL) return NULL;

thisRow-&gt; numCols后来在程序中用来访问内存,而内存分配了“numCols”,这个元素比程序试图访问的内容少一个元素。

显然,糟糕的内存访问在释放此内存时会给free()带来一些麻烦。有趣的是,在Linux机器上,这会产生一个直接的分段错误,这就是为什么我能够更容易地将其归零。

我可以通过这种方式来了解有时在提问时,甚至发布“不相关”的代码也很重要。

我自己解决了这个问题,但感谢大家的投入。没有人指出一个明显的“你的缺陷”的事实促使我深入挖掘,并评论未在此处发布的代码部分。