【问题标题】:EXC_BAD_ACCESS While calling malloc functionEXC_BAD_ACCESS 调用 malloc 函数时
【发布时间】:2011-03-20 22:39:35
【问题描述】:

我有以下功能,但有时它会在 malloc 函数调用,我不知道原因,我认为这可能是由于堆大小不足,但我已经监视了堆,并且我知道当 malloc 失败时我有足够的空间可用于内存分配,任何人都可以建议对我来说任何事

char *substr(const char *pstr, int start, int numchars)
{
 char *pnew;
 pnew=malloc(numchars+1);  //this line fails
 if (pnew==0)
 {
  free(pnew);
  pnew=malloc(numchars+1);
 }


 strncpy(pnew, pstr + start, numchars);
 pnew[numchars] = '\0';
 return pnew;

}

int32 SendData(char * dataBuffer, int CommandType) { struct sockaddr_in remoteServerAddr; int tcpSocket; 整数错误代码; 整数计数器; int PacketsToSend; int32 恢复; 字符 msgbuf[16]; 字符 * 数据包; 字符 * cmdIRes; 字符 RecPacket[BUF_SIZE]; div_t divresult;

counter = 0;
/* Specify struct sock address */
memset(&remoteServerAddr, 0, sizeof(remoteServerAddr));
remoteServerAddr.sin_len = sizeof(remoteServerAddr);
remoteServerAddr.sin_family = AF_INET;
remoteServerAddr.sin_port = htons(11000); // Net byte order required
remoteServerAddr.sin_addr.s_addr = inet_addr("10.252.85.26");

/* Create an TCP socket */
tcpSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (tcpSocket != -1)
{
    /* Connect to server */
    errorCode = connect(tcpSocket, (struct sockaddr*) &remoteServerAddr,
            sizeof(remoteServerAddr));
    if (errorCode == -1)
    {
        /* Connection failed */
        errorCode = socketerror();
        sprintf(msgbuf, "Error %d", errorCode);
        displayMsg("connect:", "Failed!!!", msgbuf, NULL, 0x0100FFFF);
    }
    else
    {
        /* Send packets */
        divresult=div(sizeof(dataBuffer), BUF_SIZE);
        PacketsToSend=divresult.quot;
        if (divresult.rem>0)
        {
            PacketsToSend=PacketsToSend+1;
        }

        while (counter < PacketsToSend)
        {

            packet= substr(dataBuffer, counter*BUF_SIZE, BUF_SIZE);
            errorCode = send(tcpSocket, packet,strlen(packet) , 0);
            if (errorCode == -1)
            {
                errorCode = socketerror();
                sprintf(msgbuf, "Error %d", errorCode);
                displayMsg("send:", "Failed!!!", msgbuf, NULL, 0x0100FFFF);
                break;
            }
            counter++;
        }
        memset(RecPacket, 0, BUF_SIZE);
        errorCode = recv(tcpSocket, RecPacket, BUF_SIZE,0);
        if (errorCode == -1)
        {
            errorCode = socketerror();
        }

        switch (CommandType)
        {
        case CommandType_SendOneTrans:
        case CommandType_SendOfflineData:
            cmdIRes=substr(RecPacket, 14, 10);
            ret= atoi(cmdIRes);
            break;

        case CommandType_TransConfirm:
            cmdIRes=substr(RecPacket, 11, 2);
            if (strcmp(cmdIRes, "ok")==0)
            {
                ret= 1;
            }
            else
            {
                ret= 0;
            }
            break;
        case CommandType_VoucherList:
            SaveVoucherList(RecPacket);
            ret= 1;
            break;

        case CommandType_Identify:
            cmdIRes= substr(RecPacket, 7, 2);
            if (strcmp(cmdIRes, "ok")==0)
            {
                ret=1;
            }
            else
            {
                ret= 0;
            }
            break;

        default:
            break;
        }



    }
    /* Close the socket */
    close(tcpSocket);
    free(RecPacket);
    free(cmdIRes);
    free(packet);
    free(msgbuf);
    return ret;
}
else
{
    errorCode = socketerror();
    sprintf(msgbuf, "Error %d", errorCode);
    displayMsg("socket:", "Failed!!!", msgbuf, NULL, 0x0100FFFF);
}
return (errorCode);

}

uint32 SendOneTrans(fin trans) { int retVal=0; int ret=0; int retValCon=0; 字符味精[100]; char * 凭证ID; 字符 * 金额; char * 终端号; char * isOnline; char * ReturnedId; 终端号=malloc(12); 凭证ID=malloc(4); 金额=malloc(7); isOnline=malloc(1); ReturnedId=malloc(3);

memset(TerminalNo, 0, sizeof(TerminalNo));
strcpy(TerminalNo, (char *)getTerminalNo());

memset(msg, 0, sizeof(msg));
if (trans.success==0)
{

    memset(msg, 0, sizeof(msg));
    memset(voucherId, 0, sizeof(voucherId));
    sprintf(voucherId, "%d", trans.voucherId);
    memset(Amount, 0, sizeof(Amount));
    sprintf(Amount, "%d", trans.Amount);

    memset(isOnline, 0, sizeof(isOnline));
    sprintf(isOnline, "%d", trans.isOnline);

    strcpy(msg, "<Req_fin>");
    strcat(msg, TerminalNo);
    strcat(msg, ",");
    strcat(msg, voucherId);
    strcat(msg, ",");
    strcat(msg, trans.cardNo);
    strcat(msg, ",");
    strcat(msg, Amount);
    strcat(msg, ",");
    strcat(msg, trans.dateOf);
    strcat(msg, ",");
    strcat(msg, trans.TimeOf);
    strcat(msg, ",1");
    strcat(msg, "<EOF>");
    retVal= SendData(msg, CommandType_SendOneTrans);

    if (retVal>=1)
    {
        sprintf(ReturnedId, "%i", retVal);
        memset(msg, 0, sizeof(msg));
        strcpy(msg, "<Req_fin_c>");
        strcat(msg, TerminalNo);
        strcat(msg, ",");

        strcat(msg, ReturnedId);
        strcat(msg, "<EOF>");
        trans.success=1;
        retValCon= SendData(msg, CommandType_TransConfirm);
        if (retValCon!=0)
        {
            trans.success=1;
            ret=1;
        }
    }

    free(msg);
    free(TerminalNo);
    free(Amount);
    free(voucherId);
    return ret;
    //free(ReturnedId);
}

}

【问题讨论】:

  • 请格式化您的代码以供显示。缩进四个空格或使用带有 101010 的按钮会有所帮助。
  • 您确定您为numchars 变量传递了正确的值吗?可能是有人将一个统一化的变量传递给这个函数吗?你能发布调用这个函数的代码吗?
  • 顺便说一句,在检查 malloc() 的结果时,最好与 NULL 进行比较。

标签: c malloc


【解决方案1】:

我不是 Apple 开发人员,但我从未在 malloc 上看到过 EXC_BAD_ACCESS,所以我不得不谷歌一下。 Apple technical FAQ 中的这个条目看起来很相关:

这类问题通常是过度释放对象的结果。 这可能非常令人困惑,因为故障往往发生在错误发生后很久。当程序深入框架代码时也可能发生崩溃,通常在你自己的代码中看不到堆栈。

【讨论】:

  • 我怀疑我添加的 free() 命令,但我不知道为什么
【解决方案2】:

您的问题更深:EXC_BAD_ACCESS 基本上意味着您过度释放内存区域。在调试器中,您会看到类似这样的内容

*** malloc[705]:对象 0×8c5b00 的错误: 已释放对象的校验和不正确 - 对象可能在被释放后被修改;在 func_name 处中断。

你的平台是什么? Guard Malloc 有空吗?如果没有,除了检查源代码之外,您当然可以这样做:

为 malloc() 编写一个包装器,它将为每个请求分配一个 vm 页面并将请求的缓冲区放在其末尾。这样,超过它的读取或写入将导致总线错误。此外,当内存是 free()'d 时,释放你的 vm 页面,这样每当你读取或写入 free()'d 时,你都会立即得到总线错误。这将需要很长时间,所以请做好准备!

【讨论】:

  • 我在eclipse IDE中写,是POS设备编程
  • 你能给我一份上述包装的样品吗?
  • 恐怕不行;如果您希望可以查看 Guard Malloc 或其他遵循相同方法的库的源代码。另外,既然你显然不是在 POS 上编码,你可以使用 valgrind 或类似的工具吗?
  • 我在 Windows 平台上编码,看来 valgrind 只支持 macOS 和 linux
【解决方案3】:
char *substr(const char *pstr, int start, int numchars)
{
 char *pnew;
 pnew=malloc(numchars+1);  //this line fails

以下内容毫无意义,您要做什么?如果 malloc 失败了为什么要再试一次,最重要的是为什么免费?您应该退出并返回 null

 if (pnew==0)   
 {
  free(pnew);
  pnew=malloc(numchars+1);
 }

我认为错误在其他地方,也许你应该检查一下 参数,确保 pstr 不是 NULL 并且 numchars > 0

【讨论】:

  • 错误发生在第一个malloc的行,我想知道这个函数第一次运行良好
【解决方案4】:

您可能在代码的前面某处损坏了 malloc 堆,但直到您调用 malloc 或 free 后问题才会出现 - 您应该在 valgrind 或类似的环境下运行代码以缩小根本原因。

【讨论】:

  • 看来你是对的,但是我怎样才能分配一个新的内存块来使用或者如果堆被损坏我该怎么办
  • @arash:您需要调试 malloc 堆损坏的原因 - 在您这样做之前,您的代码将不稳定 - 在 valgrind 它应该直接带您解决问题,然后您可以修复它,然后 malloc/free 应该再次按预期运行。
【解决方案5】:

这种螨虫有助于清理东西:

You will get EXC_BAD_ACCESS in 3 cases:

   1. An object is not initialized
   2. An object is already released
   3. Something else that is not very likely to happen

所以请评估函数中其他变量的状态,或者您可以在这里粘贴调用函数以获得更好的解决方案。

编辑:从 cmets 获取信息后代码继续。

有意避免NULL检查。

char a[][100] = {"<Req_fin>1","<Req_fin>1","<Req_fin>1<EOF>","<Req_fin>1<EOF>","<Req_fin>1","<Req_fin>1<EOF>","<Req_fin>1<EOF>","<Req_fin>1<EOF>","<Req_fin>1","<Req_fin>1<EOF>"};
char *b= "<EOF>";
char *substr(char *buff,int start,int bytes)
{
char *ptr;

ptr = malloc(bytes+1);
strncpy(ptr,buff+start,bytes);
ptr[bytes]='\0';
return ptr;
}
int main()
{
char buff[100];
int i;
char *ptr;
strcpy(buff,"Abcdef");
for(i=0;i<10;i++)
{
ptr = substr(buff,0,512);
printf("String is %s \n",ptr);
memset(buff,0,sizeof(buff));
strcpy(buff,a[i]);
strcat(buff,b);
 free(ptr);
}
return 0;
}

上面的代码工作正常。因此,如果您无法在此处粘贴您的功能,请将此作为参考。我不能只是猜测错误。

【讨论】:

  • 此函数第二次调用失败,第一次运行。在它第一次运行之后。我调用 free() 函数来释放这个函数的结果,如下所示: packet= substr(dataBuffer, counter*BUF_SIZE, BUF_SIZE); //blob 免费(数据包);但是为什么 malloc 失败了?
  • counterBUF_SIZE,这里的值是多少?假设您绕过了 dataBuffer 的分配内存,那么在函数 substr 中您正在执行无效访问。所以请粘贴调用此 linepacket= substr(dataBuffer, counterBUF_SIZE, BUF_SIZE); 的函数
  • 函数太长了,但是BUF_SIZE的值总是等于512,计数器等于0。绕过databuffer分配的内存是什么意思?当然它必须分配内存,有什么问题?
  • 所以 start 总是 0。numchars 的值是多少?为dataBuffer分配了多少内存?您也可以修剪大功能以仅粘贴相关部分。
  • databuffer 定义如下: char dataBuffer[100];正如您在这一行中看到的那样,numchars 的值为 BUF_SIZE: packet= substr(dataBuffer, counter*BUF_SIZE, BUF_SIZE);我的意思是 numchars 等于 512。
猜你喜欢
  • 2012-12-17
  • 1970-01-01
  • 2015-05-28
  • 1970-01-01
  • 2013-03-24
  • 2015-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多