user4216497
user4216497

Reputation:

exc_bad_access code 1 in C on Xcode

I'm trying to do a linked list of recettes (recipes in French)

Here is my code:

/*
 * Copyright 2015 Robeen Simeon
 * http://robeen.ca
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

typedef struct Recette Recette;
struct Recette
{
  char *nom;
  Recette *suivant;
};

typedef struct Categorie Categorie;
struct Categorie
{
  char* nom;
  Categorie *suivant;
};

Recette* addRecette(Recette *precedent, char* nomRecette);

void printRecette(Recette* recette);

void printRecettes(Recette* premiereRecette);

/* MAIN */
int main (int argc, char **argv)
{
  char *nom = malloc(256);
  nom = "poulet";
  Recette *premiereRecette;
  premiereRecette = addRecette(NULL, nom);

  char *nom2 = malloc(128);
  strcpy(nom2, "boeuf");
  Recette *deuxiemeRecette;
  deuxiemeRecette = addRecette(premiereRecette, nom2);

  printRecettes(premiereRecette);

}


/* FONCTIONS */
Recette* addRecette(Recette *precedent, char* nomRecette)
{
  Recette *recette = malloc(sizeof(*recette));

  recette->nom = nomRecette;

  if (precedent != NULL) {
    precedent->suivant = recette;
  }
  else
  {
  recette->suivant = NULL;
  }

  return recette;
}

void printRecette(Recette* recette)
{
  printf("Cette recette est : %s\n", recette->nom);
  if(recette->suivant != NULL)
  {
    printf("Sa recette suivante est : %s\n", recette->suivant->nom );
  }
  else
  {
    printf("Pas de suivant\n");
  }
}

void printRecettes(Recette* premiereRecette)
{
  Recette *recette = premiereRecette;
  while (premiereRecette->suivant != NULL) {
    printRecette(recette);
    recette = recette->suivant;
  }
}

Here is in an image the error [EXC_BAD_ACCESS(code=1, address= 0x0)] i'm getting on line 81.

Sometimes it's [EXC_BAD_ACCESS(code=EXC_l386_GPFLT)] on line 84 though.

The program still gives the right results too.

enter image description here

Upvotes: 1

Views: 309

Answers (2)

paulsm4
paulsm4

Reputation: 121649

I believe your loop should check "recette", not "premiereRecette":

void printRecettes(Recette* premiereRecette)
{
  Recette *recette = premiereRecette;
  /* while (premiereRecette->suivant != NULL) { // WRONG! */
  while (recette != NULL) { /* Better.  Note that "printRecette()" checks
                               for "recette->suivant == NULL" */
    printRecette(recette);
    recette = recette->suivant;
  }
}

ALSO:

You can use strdup combine these two lines:

char *nom2 = malloc(128);
strcpy(nom2, "boeuf");

into:

char *nom2 = strdup("boef");

This is an error:

char *nom = malloc(256);
nom = "poulet";  /* WRONG! 
                    Use "strcpy()" or "strdup()".
                    Or char *nom = "poulet"; */

And don't forget to "free()" any strings you've "malloc'ed"!

Upvotes: 0

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36401

This is not a bug in C on XCode. The error message is effectively cryptic, but your title a slightly misleading. exc_bad_access (an XCode tool message) is generally due to a try to access a forbidden memory address. If you execute your code on a terminal, you would have Segmentation violation (a well-known message for programmers).

Two bugs, in the while loop your test is the wrong one, and in the add function you didn't initialize the structure correctly:

void printRecettes(Recette* premiereRecette) {
  Recette *recette = premiereRecette;
  while (recette->suivant != NULL) { // loop on recette pointer...
    printRecette(recette);
    recette = recette->suivant;
  }
}

Recette* addRecette(Recette *precedent, char* nomRecette) {
  Recette *recette = malloc(sizeof(*recette));   
  recette->nom = nomRecette;
  recette->suivant = NULL; // initialize all fields 
  if (precedent != NULL) {
    precedent->suivant = recette;
  }
  return recette;
}

You also allocated chars for the first recipe name, that you don't use; this is a memory leak. Either forget the allocation or use strcpy as for the second recipe.

Upvotes: 2

Related Questions