C Peker forvirring

stemmer
3

Jeg ønsker å lagre en streng i minnet og lese den senere:

$$->desc.constant->base.id =  (char*)malloc(200);
sprintf($$->desc.constant->base.id, %f, $1);
printf(->%s\n, $$->desc.constant->base.id); //LINE A
printf(->%i\n, $$->desc.constant); //LINE B

//SOME OTHER CODE

//Then, later on in a function call:

printf(%i, expr->desc.constant); // LINE D
printf(%s, expr->desc.constant->base.id); // LINE C

Selv Linje B og Line D viser den samme adressen, printf i linje C mislykkes med en segmentering feil. Hva er det jeg mangler?

Eventuelle hjelpe ville virkelig være verdsatt!

Publisert på 06/12/2008 klokken 17:17
kilden bruker
På andre språk...                            


4 svar

stemmer
9

printf("->%i\n", $$->desc.constant); //LINE B

Som er ugyldig. Som du vise linjen før det som constantfaktisk er en peker, kan du ikke behandle det som om det var av type int. De trenger ikke necassarily har samme sizeof og justering. Bruk formatet som brukes for void*. Det vil produksjonen minneadresser riktig:

printf("->%p\n", (void*)$$->desc.constant); //LINE B
Svarte 06/12/2008 kl. 17:22
kilden bruker

stemmer
1
  1. alltid sjekke malloc's returverdi.
  2. sprintf -> snprintf
  3. "%f" -> "%.*g"

Her er et eksempel:

/** $ gcc print_number.c -o print_number */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{
  const char* number_format = "%.*g";
  const int ndigits = 15;
  assert(ndigits > 0);
  const int maxlen = ndigits + 8 /* -0.e+001, Infinity */ + 1 /* '\0' */;

  char *str = malloc(maxlen);
  if (str == NULL) {
    fprintf(stderr, "error: malloc\n");
    exit(1);
  }    

  double number = 12345678901234567890.123456789012345678901234567890;
  /** `number = 0/0` crashes the program */;

  printf("number: %f\t", number);

  int len_wouldbe = snprintf(str, maxlen, number_format, ndigits, number);
  assert(len_wouldbe < maxlen);

  printf("%s\n", str);
  return 0;
}

Produksjon:

number: 12345678901234567000.000000 1.23456789012346e+19
Svarte 06/12/2008 kl. 18:47
kilden bruker

stemmer
0

Gitt at programmet er å produsere en segmentering feil, tror jeg problemet er mest sannsynlig at strukturen utpekt (pekt på) med expr->desc.constanthar blitt gjenbrukt siden plassen ble tildelt, eller muligens plassen var egentlig aldri bevilget i det hele tatt.

Koden oppviser forskjellige veniell synd, for eksempel ved hjelp av sprintf()i stedet for snprintf(), og gratuitously fordele 200 byte for strengrepresentasjon av et flyttall. (Du er svært lite sannsynlig å trenge så mye plass, hvis du gjør det, bør du mest sannsynlig gi rom for minst 100 flere sifre enn du har, siden eksponenten rekkevidde for flyttall er vanligvis +/- 308, og den eneste grunnen til at du 'd trenge 200 tegn, er å gi rom for utrolig store eller små utrolig tall.)

Du har vist at $$->desc.constantpeker til samme sted, men du har ikke vist hvordan den plassen er tildelt. Du kan deretter fordele strengen plass $$->desc.constant->base.id, uten tydelig disponering av plass til base.

Svarte 06/12/2008 kl. 23:04
kilden bruker

stemmer
0

Kanskje mellom tidspunktet for de to delene av koden du har siden freed strengen?

$$->desc.constant->base.id =  (char*)malloc(200);
sprintf($$->desc.constant->base.id, "%f", $1);
printf("->%s\n", $$->desc.constant->base.id); //LINE A
printf("->%i\n", $$->desc.constant); //LINE B

//SOME OTHER CODE
// which happens to do
free($$->desc.constant->base.id);

printf("%i", expr->desc.constant); // LINE D
printf("%s", expr->desc.constant->base.id); // crash
Svarte 06/12/2008 kl. 18:15
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more