我不精通C编程,所以如果这不是一个强有力的问题,请原谅我。在下面的代码中,我只能在获取 nsamplepts
的值后将内存分配给samplesVec
,但我需要将向量samplesVec
返回给main
以供进一步使用(尚未编码)。但是,我收到以下错误:
终端窗口中的错误:导入扫描(3497,0x7fff7b129310) malloc: * 对象 0x7fdaa0c03af8 的错误:未分配正在释放的指针* 在malloc_error_break中设置断点进行调试中止陷阱:6
我正在使用带有gcc编译器的Mac OS X Mavericks。感谢您的任何帮助。
*已编辑!!在评论员的宝贵意见之后,以下内容代表了原始问题的解决方案(不再可用)*
下面的代码修改似乎解决了我原来的问题。感谢大家的宝贵意见!
/* Header Files */
#define LIBAIFF_NOCOMPAT 1 // do not use LibAiff 2 API compatibility
#include <libaiff/libaiff.h>
#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <math.h>
/* Function Declarations */
void FileSearch(char*, char*, char*, char*, char*);
int32_t *ImportSweeps(char*);
/* Main */
int main()
{
char flag1[2] = "N";
char binname[20] = "bin1"; // dummy assignment
char buildfilename[40] = "SweepR";
char skeletonpath[100] = "/Users/.../Folder name/";
int k, len;
/* Find the sweep to be imported in the directory given by filepath */
FileSearch(skeletonpath, binname, buildfilename, skeletonpath, flag1);
if (strcmp(flag1,"Y")) {
printf("No file found. End of program.n");
} else {
len = (int) strlen(skeletonpath);
char *filepath = malloc(len);
for (k = 0; k < len; k++) {
filepath[k] = skeletonpath[k];
}
printf("File found! Filepath: %sn", filepath);
// Proceed to import sweep
int32_t *sweepRfile = ImportSweeps(filepath);
if (sweepRfile) {
printf("Success!n");
// Do other things with sweepRfile
free(sweepRfile);
}
free(filepath);
}
return 0;
}
/* Sub-Routines */
void FileSearch(char *dir, char *binname, char *buildfilename, char* filepath, char* flag1)
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;
if((dp = opendir(dir)) == NULL) {
fprintf(stderr,"Cannot open directory: %sn", dir);
return;
}
chdir(dir);
while((entry = readdir(dp)) != NULL) {
lstat(entry->d_name, &statbuf);
if(S_ISDIR(statbuf.st_mode)) {
/* Found a directory, but ignore . and .. */
if(strcmp(".",entry->d_name) == 0 || strcmp("..",entry->d_name) == 0)
continue;
strcpy(binname,entry->d_name);
strcpy(buildfilename,"SweepR");
/* Recurse at a new indent level */
FileSearch(entry->d_name, binname, buildfilename, filepath, flag1);
}
else {
sprintf(buildfilename, "%s%s.aiff", buildfilename, binname);
if (strcmp(entry->d_name,buildfilename)) {
strcpy(buildfilename,"SweepR");
} else {
sprintf(filepath, "%s%s/%s", filepath, binname, buildfilename);
strcpy(flag1,"Y");
break;
}
}
}
chdir("..");
closedir(dp);
}
int32_t *ImportSweeps(char *filepath)
{
char *filepathread = filepath;
/* Initialize files for importing */
AIFF_Ref fileref;
/* Intialize files for getting information about AIFF file */
uint64_t nSamples;
int32_t *samples = NULL;
int32_t *samplesVec = NULL;
int channels, bitsPerSample, segmentSize, ghost, nsamplepts;
double samplingRate;
/* Import Routine */
fileref = AIFF_OpenFile(filepathread, F_RDONLY) ;
if(fileref)
{
// File opened successfully. Proceed.
ghost = AIFF_GetAudioFormat(fileref, &nSamples, &channels, &samplingRate, &bitsPerSample, &segmentSize);
if (ghost < 1)
{
printf("Error getting audio format.n");
AIFF_CloseFile(fileref); return (int32_t) 0;
}
nsamplepts = ((int) nSamples)*channels;
samples = malloc(nsamplepts * sizeof(int32_t));
samplesVec = malloc(nsamplepts * sizeof(int32_t));
ghost = AIFF_ReadSamples32Bit(fileref, samples, nsamplepts);
if (ghost) {
for (int k = 0; k < nsamplepts; k++) {
samplesVec[k] = *(samples+k);
}
}
free(samples);
AIFF_CloseFile(fileref);
}
return samplesVec;
}
我所知... :-)
samplesVec
,如果 ImportSweeps
的返回值为 false,则不初始化fileref
。如果samplesVec
没有显式初始化,则自动(==局部)变量无法保证其值 - 换句话说,samplesVec
可以携带任何地址。如果samplesVec
不是靠运气NULL
(另一方面,情况可能经常如此),你试着free
一个未分配的内存垃圾,或者运气不好,在其他地方分配了一个。
如果我的猜测是正确的,您可以通过以下方式轻松解决此问题:
int32_t *samples;
int32_t *samplesVec = NULL;
无论如何,如果您不在下一行中使用它,那么尽快使用一些有意义的错误或虚拟值初始化任何变量都是一个好主意。由于指针是可怕的野兽,如果我不在声明中使用有用的值初始化它们,我总是NULL
它们。
编辑:几个小的更改,以获得英语的可读近似值。
如果AIFF_OpenFile失败,ImportSweeps 将返回一个未定义的值,因为 samplesVec 未初始化。如果该值为非 NULL,main 将尝试释放它。您可以初始化 samplesVec = NULL,也可以将代码重新组织为
fileref = AIFF_OpenFile(filepathread, F_RDONLY) ;
if(!fileref) {
{
// print error message here
return NULL;
}
// File opened successfully. Proceed.
...
有些人会坚持一个应该只有一个出口的函数——他们消息不灵通,并说出一个错误的教条,这些教条是从同样不知情和教条的其他人那里传下来的。上面的错误和返回检查称为保护子句。每次测试成功时缩进的替代样式会产生更难阅读、更难修改且更容易出错的箭头反模式。有关一些讨论,请参阅 http://blog.codinghorror.com/flattening-arrow-code/和 http://c2.com/cgi/wiki?ArrowAntiPattern。