当我运行尝试释放此结构中的任何内容时,我遇到了问题。首先是标题中的结构定义:
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() 有一些不明白的地方,但似乎如果我可以从 struct 成员访问有效数据而不会出现错误并且不会导致崩溃,那么 free 应该能够释放具有被malloc'd。
也许我只是通过到处传递这些指针来做坏事(比如将指向“line”的指针传递给将其分配给结构成员的函数),但在我看来,这一切都很好。我知道结构的每个成员都被 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 是我需要与数学库链接的特定信号处理代码,在此示例中,我已将其简化为不调用这些函数以排除它们的位置)
我正在使用这个版本的 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 版本,它会在运行中的不同点出现段错误。在几次运行中,它甚至在没有段错误的情况下通过了一次,所以也许我遇到了编译器问题。因为我有 cygwin,所以编译器可能是混合实用程序和链接器(使用“/bin”的错误目录)。
既然我已经包含了 rowDestructor() 代码,我希望我已经包含了足够的内容来清楚地说明我正在使用这些 malloc 指针做什么。感谢到目前为止的评论。
如果我的 C 实现本身有任何问题,我想修复它。与此同时,我将清理我的开发环境,看看是否可以通过确保所有组件的正确路径来获得更好的结果。