Proč to jednoduchý úkol řetězec segfault?

hlasů
4

Mám následující kód:

#include <iostream>
using namespace std;
int main()
{
    char* a = foo;
    char* b = bar;
    a = b;
    cout << a << ,  << b << endl;
    return 0;
}

To kompiluje a pracuje, tzn. tiskne bar, bar. Nyní bych chtěl ukázat, že to, co se tady děje, není kopírování řetězec. Chtěl bych změnit ba ukázat, že ataké mění. Přišel jsem s tímto jednoduchým kódem:

#include <iostream>
using namespace std;
int main()
{
    char* a = foo;
    char* b = bar;
    a = b;
    b[1] = 'u'; // ← just this line added
    cout << a << ,  << b << endl;
    return 0;
}

... ale to segfault chyb. Proč? Zajímavé na tom je, že tyto modifikace běží v pohodě:

#include <iostream>
using namespace std;
int main()
{
    char* a = foo;
    char b[] = bar; // ← declaration changed here
    a = b;
    b[1] = 'u';
    cout << a << ,  << b << endl;
    return 0;
}

Proč to segfault jako ta předchozí? Myslím, že jsem chybí některé důležité rozdíly mezi ukazatele stylu a inicializace řetězec array stylu.

Položena 05/03/2009 v 10:31
zdroj uživatelem
V jiných jazycích...                            


6 odpovědí

hlasů
9

Nemůžete změnit řetězcové konstanty, což je to, co dostanete, když použijete syntaxi pointer-to-doslovný jako v prvních ukázky kódu.

Podívejte se také na tuto otázku: Je řetězec doslovný v C ++ vytvořen ve statické paměti? ,

Odpovězeno 05/03/2009 v 10:33
zdroj uživatelem

hlasů
6

Když píšete toto:

char *b = "bar";

kompilátor přidělí anonymní (bezejmenný) oblast paměti pro ukládání řetězec doslovný „bar“. Řetězcové literály nemohou být modifikována, takže kompilátor (pomocí spojovníku a operačního systému) uvede řetězec doslovný v části paměťového prostoru běžícím programu, který je chráněn proti zápisu. Při pokusu o jeho změně, operační systém ho zachytí a způsobuje váš program segmentace poruchy.

(Váš kód C ++, C ne, ale to je nepodstatné na tuto otázku.)

Odpovězeno 05/03/2009 v 10:34
zdroj uživatelem

hlasů
-1

Tento rozdíl je možná kompilátor specifické. Ukázat svůj bodový použití malloc alokovat buffer, zkopírujte řetězec do této vyrovnávací paměti a nezapomeňte použít zdarma, pokud již nepotřebujete řetězec.

Odpovězeno 05/03/2009 v 10:34
zdroj uživatelem

hlasů
2

Když píšete:

char *foo = "bar";

Co se vlastně stane, je, že „bar“ je uložena v segmentu read-only paměti. Proto je neměnná. Získáte segfault protože pokusu upravit segment jen pro čtení.

Odpovězeno 05/03/2009 v 10:35
zdroj uživatelem

hlasů
2

Můžete také ukazují, že ‚a‘ byl změněn vytištěním hodnotu ukazatele.

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;

    cout << (void*)a << ", " << (void*)b << endl;
}

To bude tisknout na adresu, která ‚a‘ a ‚b‘ bodu.
Máte na obsazení na ‚void *‘, protože operátor << přetížení na ‚char *‘, aby vytisknout Řetězec jakýkoli jiný ukazatel vytiskne adresu.

Odpovězeno 05/03/2009 v 10:43
zdroj uživatelem

hlasů
1

Teoreticky řetězec doslovný by neměl být schopen přiřadit char * pouze ‚const char *‘. Pak by kompilátor zastavit dříve, než jste napsal SEG chybující kód.

Odpovězeno 05/03/2009 v 12:44
zdroj uživatelem

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