【问题标题】:Pointer being freed was not allocated, Abort trap: 6被释放的指针未被分配,中止陷阱:6
【发布时间】:2014-04-05 11:20:25
【问题描述】:

我不精通 C 编程,所以如果这不是一个强烈的问题,请原谅。在下面的代码中,我只能在获得nsamplepts的值后给samplesVec分配内存,但是我需要将向量samplesVec返回给main以供进一步使用(尚未编码)。但是,我收到以下错误:

终端窗口中的错误: ImportSweeps(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: %s\n", 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: %s\n", 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;
}

【问题讨论】:

  • ImportSweeps 返回什么?我之所以问,是因为这部分代码看起来很可疑,因为 sizeof(sweepRfile)/sizeof(int32_t) 并没有按照您的想法执行...
  • @John3136 ImportSweeps 应该返回一个名为 samplesVec 的大向量,其中包含 int32_t 类型的数据(在我正在使用的 libaiff 库中定义)。
  • 那没关系,但是你打印出来的长度会出错(指针大小/ int大小)可能是1。
  • @John3136 即使我从代码中删除sizeof(sweepRfile)/sizeof(int32_t),我也会遇到同样的错误。
  • 是的,从来没有说过这是你的问题,只是说这是一个问题。您需要找出导致问题的免费软件...

标签: c pointers malloc free


【解决方案1】:

所以...据我所知... :-)

samplesVec,ImportSweeps的返回值没有初始化,如果fileref为false。如果samplesVec 未显式初始化,则自动(== 局部)变量无法保证其值——换句话说,samplesVec 可以携带任何地址。如果 samplesVec 不是 NULL 运气好(另一方面可能经常出现这种情况),您可以尝试 free 一个未分配的垃圾内存,或者运气不好,在其他地方分配了一个。

如果我的猜测是正确的,您可以通过以下方式轻松解决此问题:

int32_t *samples;
int32_t *samplesVec = NULL;

无论如何,如果您不在下一行使用它,最好尽快用一些有意义的错误或虚拟值初始化任何变量。由于指针是可怕的野兽,如果我不在声明时使用有用的值初始化它们,我总是 NULL 它们。

编辑:对英语的可读近似进行了一些小的小改动。 :-)

【讨论】:

  • samplesVec 已初始化。我通过打印它的第二个值来检查它。我还在free(samples) 之后给出了printf("Test\n"); 命令并执行了该命令。但看起来samplesVec 没有返回到main,因为写在int32_t *sweepRfile = ImportSweeps(filepath); 行之后的printf("Test\n"); 命令没有被执行。
  • 我在你的代码中看不到任何关于使用免费的额外错误,因为你使用AIFF_OpenFile 是正确的。当然,您的库函数之一总是有可能使用 malloc()/free() 并且有问题或得到其他意外输入。
  • 我发现了一些东西......也许你可以帮我找出问题......在主函数中,如果我绕过函数FileSearch(filepath, binname, buildfilename, filepath, flag1);,请将char filepath[100] = "/Users/.../Foldername/";更改为包含FileSearch 通常会找到的文件(我相信这是正确的 - 它们具有相同的长度)并将char flag1[2] = "Y"; 设置为函数int32_t *ImportSweeps(char *filepath),然后我需要包含AIFF_CloseFile(fileref);。只要绕过 FileSearch 功能,一切似乎都正常。
【解决方案2】:

如果 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 进行一些讨论。

【讨论】:

  • 我试过你的方法没有用。回应我之前的评论:samplesVec 已初始化。我通过打印它的第二个值来检查它。我还在free(samples) 之后给出了printf("Test\n"); 命令并执行了该命令。但看起来samplesVec 没有返回到main,因为写在int32_t *sweepRfile = ImportSweeps(filepath); 行之后的printf("Test\n"); 命令没有被执行。
  • 嗯,samplesVec没有初始化;看,就在那里——int32_t *samples, *samplesVec; 没有初始化程序。它得到set,但前提是fileref 不为NULL。至于 printf 语句 - printf 被缓冲,如果程序崩溃,您将看不到输出。永远不要将它用于调试输出——改用 fprintf(stderr, ...)。
  • 感谢您的 cmets。我刚刚在我的程序中初始化了samplesVec(按照 Mark A. 的建议设置为 NULL)。所以我已经解决了这个问题,但原来的问题仍然存在。
  • 当我摆脱 AIFF_CloseFile(fileref); 时,程序可以工作,但根据 libaiff 库的文档,我认为我不应该这样做。
  • @Rahul 你可能在某处写了超出 malloced 内存范围的内容,并将 malloc 混淆为认为某些分配的部分不是。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 2018-09-30
相关资源
最近更新 更多