Domanda

Voglio archiviare una stringa in memoria e leggerla in seguito:

$->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

Sebbene la riga B e la riga D mostrino lo stesso indirizzo, la stampa nella riga C non riesce con un errore di segmentazione. Cosa mi sto perdendo?

Qualsiasi aiuto sarebbe davvero apprezzato!

È stato utile?

Soluzione

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

Non è valido. Mentre mostri alla riga precedente che costante è in realtà un puntatore, non puoi trattarlo come se fosse di tipo int . Non hanno necessariamente la stessa dimensione e allineamento. Utilizza il formato utilizzato per void * . Produrrà correttamente gli indirizzi di memoria:

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

Altri suggerimenti

  1. sempre controlla il valore di ritorno di malloc .
  2. sprintf - > snprintf
  3. "% f " - > ".% * G "

Ecco un esempio:

/** $ 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;
}

Output:

number: 12345678901234567000.000000 1.23456789012346e+19

Forse tra il tempo dei due pezzi di codice che hai dalla libera alla stringa?

$->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

Dato che il programma sta producendo un errore di segmentazione, penso che il problema sia molto probabile che la struttura designata (indicata da expr- > desc.constant sia stata riutilizzata da quando lo spazio era allocato, o forse lo spazio non è mai stato realmente assegnato affatto.

Il codice mostra vari peccati veniali, come l'uso di sprintf () invece di snprintf () e l'allocazione gratuita di 200 byte per la rappresentazione in stringa di un numero in virgola mobile . (È molto improbabile che tu abbia bisogno di così tanto spazio; in tal caso, molto probabilmente dovresti consentire almeno 100 cifre in più rispetto a te, poiché l'intervallo di esponenti per i numeri in virgola mobile è di solito +/- 308 e l'unica ragione per cui occorrerebbero 200 caratteri per consentire numeri incredibilmente grandi o incredibilmente piccoli.)

Hai dimostrato che $$ - > desc.constant punta allo stesso posto, ma non hai mostrato come è assegnato tale spazio. Quindi alloca lo spazio delle stringhe in $$ - > desc.constant- > base.id , senza allocare chiaramente lo spazio per base .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top