首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C- free malloc'd结构成员和结构

C- free malloc'd结构成员和结构
EN

Stack Overflow用户
提问于 2013-06-06 09:22:34
回答 1查看 2.5K关注 0票数 4

当我尝试释放这个结构中的任何东西时,我遇到了一个问题。首先是头部中的结构定义:

代码语言:javascript
复制
    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 ;

然后这里是可以创建结构实例的地方:

代码语言:javascript
复制
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;

下面是"line“是如何创建的:

代码语言:javascript
复制
char* RBreadLine(fifo_t* fifo)
{
char* outbuf = NULL;
.
.
.
outbuf = (char*) malloc(sizeof(char)*(cnt+1));
.
.
.
return outbuf;
}

最后是调用序列:

代码语言:javascript
复制
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()时):

代码语言:javascript
复制
 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()有一些不理解的地方,但似乎如果我可以从struct成员访问有效数据而不会出错,并且不会导致崩溃,那么free应该能够释放已经malloc的mem。

也许我只是通过到处传递这些指针来做一些不好的事情(就像将指向"line“的指针传递给一个函数,该函数将其赋值给一个struct成员),但在我看来,这一切都被考虑得很好。我知道结构的每个成员都被malloc了,所以我应该能够在我工作的过程中释放所有的东西,然后释放结构。然后,我可以将另一个指针转储到row结构上,并再次执行它。

我这样做的原因是因为我希望能够处理非常大的数据集。这是对一个程序的结构化重写,这个程序过去是用fread将所有数据加载到内存中,然后处理它,但我的一些数据集导致计算机耗尽memory...so,我将求助于块处理方法。

一旦我可以成功地释放一行,那么我就可以在此基础上构建一个row_t**,我可以使用先进先出缓冲区的概念将行循环到row_t**上,这将允许我以合理的量向前和向后查找文本文件(比如应用FIR过滤器),但不需要将整个文件加载到内存中。

例如,行FIFO会将这些新的row_t*结构存储到row_t**上,然后在填满循环缓冲区并开始覆盖旧的pointers...this之后释放旧的结构。

我认为有了这个问题的答案将是我对malloc()和free()理解的一个突破,或者可能澄清一些关于指针和结构的东西。

感谢您的任何意见。

编辑:我很抱歉忽略了我问题中最重要的部分:

代码语言:javascript
复制
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);
}

而且,由于其他人提到了编译器标志,下面是我所使用的:

代码语言:javascript
复制
gcc  -Wall laproc.c utils.c csvsurgeon.c -lm -o csv-surgeon

(laproc.c是我需要与数学库链接的特定信号处理代码,在本例中,我将其简化为不调用这些函数以排除它们)

我用的是这个版本的gcc:

代码语言:javascript
复制
$ 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重新编译:

代码语言:javascript
复制
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)

和另一个版本

代码语言:javascript
复制
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”目录)。

既然我已经包含了rowDestructor()代码,我希望我已经包含了足够的内容,可以清楚地说明我正在对这些错误定位的指针做什么。感谢你到目前为止的评论。

如果我的C实现本身就有什么问题,我想要修复它。同时,我将清理我的开发环境,看看是否可以通过确保所有组件的正确路径来获得更好的结果。

EN

回答 1

Stack Overflow用户

发布于 2013-06-20 01:47:07

事实证明,我的内存管理是很好的(难怪我费了很大劲)。我在Linux上编译了这个程序,很快就发现了一个分配内存的"off by one“错误,因此我访问的内存超出了范围。Linux机器上的程序故障是直接发生的,而Windows会让程序运行一段时间,然后终止它。

对于那些感兴趣的人来说,这就是问题所在:

代码语言:javascript
复制
 row_t* delimitLine(char* line, char* delimList, char delimListSize)
{
//<Analyze "line" to count number of data fields>
.
.
.

这就是它是如何做到的:

代码语言:javascript
复制
//Populate Row Data 
thisRow->numCols = numCols+1;   

它是这样修复的:

代码语言:javascript
复制
//Populate Row Data 
numCols+=1;
thisRow->numCols = numCols; 

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

代码语言:javascript
复制
.
.
.
    //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->numCols在稍后的程序中被用来访问内存,而内存已经被分配了"numCols",这将比程序试图访问的元素少一个元素。

显然,错误的内存访问在释放内存时给free()带来了一些麻烦。有趣的是,在Linux机器上,这产生了一个直接的分段错误,这就是为什么我能够更容易地专注于这个问题。

我可以将此归结为学习到,有时当提出问题时,甚至发布“无关”的代码也是很重要的。

我自己解决了这个问题,但还是要感谢大家的投入。事实上,没有人指出一个显而易见的“你的缺陷”,这促使我更深入地挖掘,并评论这里没有张贴的代码部分。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16952314

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档