Subproceso 1: EXC_BAD_ACCESS (código = 1, dirección = 0x0) problema de memoria C estándar

6 minutos de lectura

avatar de usuario
zeus_masta_funk

Estoy escribiendo código para comparar dos archivos de entrada en C estándar, usando el IDE de Xcode. Sigo recibiendo este error: Subproceso 1: EXC_BAD_ACCESS (código = 1, dirección = 0x0). He leído un poco sobre esto y creo que es un problema de memoria, pero no importa lo que intente, parece que no puedo solucionarlo (también intenté hacer las estructuras dinámicamente usando malloc y lo enumeré en la parte inferior de el código). Es extraño porque escribe todos los datos y luego escupe ese error al final. El formato del archivo es algo como esto: start(int)..stop(int) id(+ o -) ahora algunas cosas que no me importan para el resto de la línea. Acabo de probar esto en un archivo con solo + id, por lo que el aspecto “-” no es parte del problema. De todos modos, estoy bastante cansado y he estado mirando esto durante algunas horas, así que perdónenme si no tiene sentido, lo actualizaré después de algunas horas de sueño.

typedef struct
{
  int start;
  int stop;
  char *strandID;
} location;

int main(int argc, const char * argv[])
{
  if (argc != 4)
  {
    fprintf(stderr,
        "Usage is ./a.out windowfile.txt genefile.txt outputFileName");
    exit(-1);
  }

  //const vars
  const char *windowInput = argv[1];
  const char *geneInput = argv[2];
  const char *outputfile = argv[3];

  const int windowHeader = 9;
  const int geneHeader = 3;

  //get size of structures -- I have debugged and these work correctly, returning the size of my structure
  const int posWsize = getSize(windowInput, "+", windowHeader);
  const int negWsize = getSize(windowInput, "-", windowHeader);
  const int posGsize = getSize(geneInput, "+", geneHeader);
  const int negGsize = getSize(geneInput, "-", geneHeader);

  //declare structs
  location posWindow[posWsize];
  location negWindow[negWsize];
  location posGene[posGsize];
  location negGene[negGsize];

  //extract data here
  getLocations(posWindow, negWindow, windowInput, windowHeader);
  return 0;
}

void getLocations(location *posL, location *negL, const char *input,
    const int header)
{
  FILE *fileptr = NULL;
  fileptr = fopen(input, "r"); //open file

  if (fileptr == NULL)
  { //check for errors while opening
    fprintf(stderr, "Error reading %s\n", input);
    exit(-1);
  }

  char tmpLoc[20];
  char tmpID[2];
  int eofVar = 0;
  int lineCount = 0;

  while (lineCount < header)
  { //skip header and get to data
    eofVar = fgetc(fileptr);
    if (eofVar == '\n')
      lineCount++;
  }

  int pCount = 0;
  int nCount = 0;

  while (eofVar != EOF)
  {
    fscanf(fileptr, "%s %s", tmpLoc, tmpID); //scan in first two strings
    if (!strcmp(tmpID, "+"))
    { //if + strand
      char *locTok = NULL;
      locTok = strtok(tmpLoc, ".."); //tok and get values
      posL[pCount].start = atoi(locTok);
      locTok = strtok(NULL, "..");
      posL[pCount].stop = atoi(locTok); //ERROR IS SHOWN HERE

      posL[pCount].strandID = tmpID;
      printf("start=%d\tstop=%d\tID=%s\tindex=%d\n", posL[pCount].start,
          posL[pCount].stop, posL[pCount].strandID, pCount);
      pCount++;
    }
    else if (!strcmp(tmpID, "-"))
    { //if - strand
      char *locTok = NULL;
      locTok = strtok(tmpLoc, ".."); //tok and get values
      negL[nCount].start = atoi(locTok);
      locTok = strtok(NULL, "..");
      negL[nCount].stop = atoi(locTok);

      negL[nCount].strandID = tmpID;
      nCount++;
    }

    while ((eofVar = fgetc(fileptr)) != '\n')
    {
      if (eofVar == EOF)
        break;
    }
  }

  fclose(fileptr);
}

//dynamic way...same issue -- just replace this with the above if statement and use the create location function
if (!strcmp(tmpID, "+"))
{ //if + strand
  int locStart;
  int locStop;

  locStart = atoi(strtok(tmpLoc, ".."));//tok and get values
  locStop = atoi(strtok(NULL, ".."));

  posL[pCount] = *createlocation(locStart, locStop, tmpID);

  pCount++;
}

location *createlocation(int start, int stop, char *strandID)
{
  location *tmp = NULL;
  tmp = (location *) malloc(sizeof(location) * 1);

  tmp->start = start;
  tmp->stop = stop;
  tmp->strandID = (char *) malloc(sizeof(char) * 2);
  strcpy(tmp->strandID, strandID);

  return tmp;
}

  • Siendo el código de dirección 0x0 sugiere una deferencia de puntero NULL.

    – Tangrs

    8 de octubre de 2013 a las 5:37

  • Stacktrace o no sucedió. Además, el programa no se compila, por lo que no puedo obtener mi propio seguimiento de pila.

    – troyano

    8 de octubre de 2013 a las 6:09


  • ¿Ejecutaste el código a través del depurador Xcode?

    – sueño relajado

    8 de octubre de 2013 a las 7:26

  • @dreamlax Parecía haber solucionado el problema, pero para responder a su pregunta, estaba usando puntos de interrupción para revisar mi código. No sé cómo usar el depurador de Xcode. La mayoría de los recursos que he buscado son solo obj-c y principalmente uso c estándar para mi trabajo. Si conoce algún recurso gratuito sobre la depuración del estándar c en Xcode, ¡me encantaría verlo! Gracias

    – zeus_masta_funk

    8 oct 2013 a las 16:42

  • @trojanfoe Lo siento, pero no estoy familiarizado con el seguimiento de la pila. ¿Cómo haría eso en Xcode.

    – zeus_masta_funk

    8 oct 2013 a las 16:45

Compruebe el valor de retorno de strtok.

En tu código aquí

locTok = strtok(NULL, "..");
posL[pCount].stop = atoi(locTok); //ERROR IS SHOWN HERE

strtok está devolviendo un puntero NULL y de acuerdo con documentación,

Se devuelve un puntero nulo si no quedan tokens para recuperar.

que coincide con mi suposición original de que debido a que el código de dirección es 0x0 hay una deferencia de puntero NULL en alguna parte.

Obviamente, la siguiente llamada a atoi está esperando un puntero que no sea NULL y se bloquea.

  • Al final de mi segundo bucle while en getLocations, la transmisión continúa solo hasta el carácter de nueva línea. Por lo tanto, escanearía todos los datos, llegaría al eof y luego pasaría por el bucle while una vez más. Eso hizo que scanf buscara en EOF la primera cadena y NULL la segunda, lo que provocó un error en la segunda conversión atoi. Lo arreglé agregando ‘eofVar = fgetc(fileptr);//buscar eof if (eofVar == EOF) break; else eofVar = ungetc(eofVar, fileptr);’ después de escanear hasta el final de la línea. Si tienes un método más eficiente, ¡házmelo saber! Gracias de nuevo.

    – zeus_masta_funk

    8 oct 2013 a las 16:37


También puede usar el punto de interrupción de excepción en Xcode.

Un punto de interrupción de excepción le dice al depurador que haga una pausa cada vez que se encuentre un problema en cualquier parte de su programa, para que pueda evaluar el estado de su programa antes de que falle.

Vaya a Navegación de puntos de interrupción (Cmd+8), luego haga clic en el botón + en la parte inferior izquierda y elija Agregar punto de interrupción de excepción. Puedes dejarlo ahí.

ingrese la descripción de la imagen aquí

para xc

en tus main() función, intente eliminar char*argv[] o ambos argumentos.

  • Hola, bienvenido a SO. A su publicación le faltan detalles cruciales y no es obvio con qué necesita ayuda. ¿Por qué no pegas un ejemplo de código? Aquí hay una guía SO sobre cómo hacer buenas preguntas

    – Konrads

    12 de mayo de 2020 a las 3:46

En mi caso, estaba usando el tipo de bloque incorrecto. Por alguna razón, un desarrollador había marcado un bloque como const id blockName = ^(Type variableName) { /* code */ } but unfortunately the Type mismatched . Because nombre de bloquewas declared as typeidentificación, the compiler could not warn me properly when I passed blockName` como un argumento en otro lugar, y este error ocurrió en tiempo de ejecución.

Por ejemplo:

    const id callback = ^(ARTPaginatedResult<ARTMessage *> * _Nullable paginatedResult, ARTErrorInfo * _Nullable error) { /* code */

    [channel setOptions:channelOptions callback:callback];

El bloque de arriba tiene 3 parámetros, pero channel:setOptions:callback: define 1 argumento llamado callbackque debe ser un bloque que toma 1 argumento y se declara como

- (void)setOptions:(ARTRealtimeChannelOptions *_Nullable)options callback:(nullable void (^)(ARTErrorInfo *_Nullable))cb;

Debe eliminar los argumentos de su función principal. Y funcionará.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad