EXC_BAD_ACCESS при вызове функции malloc - PullRequest
3 голосов
/ 26 июля 2010

У меня есть следующая функция, но иногда происходит сбой при вызове функции 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 errorCode;int counter;int PacketsToSend;int32 ret;char msgbuf [16];символ * пакет;char * cmdIRes;char 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;символ msg [100];char * voucherId;символ * Сумма;char * TerminalNo;char * isOnline;char * ReturnedId;TerminalNo = таНос (12);voucherId = таНос (4);Сумма = таНос (7);isOnline = таНос (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);
}

}

Ответы [ 5 ]

2 голосов
/ 26 июля 2010

Ваша проблема глубже: EXC_BAD_ACCESS в основном означает, что вы чрезмерно освобождаете зоны памяти.В отладчике вы увидите что-то вроде этого

*** malloc [705]: ошибка для объекта 0 × 8c5b00: неверная контрольная сумма для освобожденного объекта - объект, вероятно, был изменен после освобождения;перерыв на func_name.

Какая у вас платформа?Страж Маллок доступен для вас?Если нет, то вот что вы можете сделать, кроме тщательного изучения вашего исходного кода, конечно:

Напишите оболочку для malloc (), которая будет выделять одну страницу vm для каждого запроса и помещать запрошенный буфер в ее конец.Таким образом, чтение или запись после этого вызовет ошибку шины.Кроме того, когда память свободна () d, освободите свои страницы vm, чтобы при чтении или записи в free () d вы сразу же получали ошибку шины.Это займет много времени, так что будьте готовы!

2 голосов
/ 26 июля 2010

Я не разработчик Apple, но я никогда не видел EXC_BAD_ACCESS на malloc, поэтому мне пришлось поискать его в Google. Эта запись из Технического FAQ Apple выглядит актуальной:

Эта проблема обычно является результатом чрезмерного освобождения объекта. Это может быть очень запутанным, так как сбой обычно происходит после того, как ошибка была совершена. Сбой также может произойти, когда программа глубоко погружена в код фреймворка, часто, когда ваш собственный код не отображается в стеке .

1 голос
/ 26 июля 2010
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);
 }

Я думаю, что ошибка в другом месте, возможно, вам следует проверить in-параметры, убедиться, что pstr не NULL и numchars> 0

0 голосов
/ 26 июля 2010

Вы, вероятно, повредили свою кучу malloc где-то ранее в коде, но проблема не проявляется, пока вы не вызовете malloc или free - вы должны запустить код под valgrind или аналогичным, чтобы сузить основную причину.

0 голосов
/ 26 июля 2010

Эта лепта помогает очистить вещи:

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

Поэтому, пожалуйста, оцените состояние других переменных в функции или вы можете вставить вызывающую функцию здесь, чтобы получить лучшие решения.

РЕДАКТИРОВАТЬ: код продолжается после получения информации из комментариев.

Проверка 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;
}

Приведенный выше код работает нормально. Поэтому, пожалуйста, используйте это как ссылку, если вы не можете вставить свою функцию здесь. Я не могу просто угадать ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...