Visualizzazione dei risultati da 1 a 9 su 9
  1. #1
    Utente di HTML.it
    Registrato dal
    Dec 2004
    Messaggi
    286

    [C] puntatore a costante stringa.

    codice:
    char *pcstr = "Costante!";

    Esiste un modo per valutare in runtime se un puntatore punta ad una costante?
    Ultima modifica di Paulin; 18-10-2014 a 13:10

  2. #2
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,462
    Probabilmente una via è questa (compilato con Visual C++) ... ma se ti serve strettamente con il C, non penso si possa

    codice:
    
    #include <iostream>
    #include <excpt.h>
    
    
    using namespace std;
    
    
    int main() 
    {
        char *pcstr = "Costante!";
        bool isc=false;
    
    
        __try 
        {
            isc=false;
            *pcstr=*pcstr; 
        } __except(EXCEPTION_EXECUTE_HANDLER) 
        {   
            isc=true;
        }
    
    
        if(isc) 
            cout << "E' UNA COSTANTE" << endl;
        else
            cout << "Non e' una costante" << endl;
    }

    Ma perché ti serve? Curiosità didattica o una necessità specifica magari affrontabile diversamente?
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  3. #3
    Utente di HTML.it
    Registrato dal
    Dec 2004
    Messaggi
    286
    Grazie Oregon, interessante soluzione. Stavo eseguendo un crash-test di alcune funzioni delle mie librerie personalizzate. Il mio scopo è proprio quello di produrre codice più sicuro. Ad esempio, progettando una funzione come potrebbe essere:

    codice:
    size_t GetTexLineA(const char *pText, int idx, char *pline)
    l'argomento pline dovrebbe essere un puntatore ad un buffer che riceverà una copia della linea idx, ma se qualcuno dovesse fornire per sbaglio il puntatore ad una costante di testo, la funzione ovviamente produrrebbe un crash!

  4. #4
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,462
    Puoi sempre far lavorare la funzione su una copia della stringa.
    No MP tecnici (non rispondo nemmeno!), usa il forum.

  5. #5
    Quote Originariamente inviata da oregon Visualizza il messaggio
    Probabilmente una via è questa (compilato con Visual C++) ...
    In generale non è una buona idea, si va incontro agli stessi problemi di IsBadWritePtr.
    Quote Originariamente inviata da Paulin Visualizza il messaggio
    l'argomento pline dovrebbe essere un puntatore ad un buffer che riceverà una copia della linea idx, ma se qualcuno dovesse fornire per sbaglio il puntatore ad una costante di testo, la funzione ovviamente produrrebbe un crash!
    Meglio, un crash immediato fa notare subito al programmatore che ha sbagliato ad usare la tua funzione. Citando dal primo link di cui sopra:
    "But what should I do, then, if somebody passes me a bad pointer?"

    You should crash.

    No, really.

    In the Win32 programming model, exceptions are truly exceptional. As a general rule, you shouldn't try to catch them. And even if you decide you want to catch them, you need to be very careful that you catch exactly what you want and no more.

    Trying to intercept the invalid pointer and returning an error code creates nondeterministic behavior. Where do invalid pointers come from? Typically they are caused by programming errors. Using memory after freeing it, using uninitialized memory, that sort of thing. Consequently, an invalid pointer might actually point to valid memory, if for example the heap page that used to contain the memory has not been decomitted, or if the uninitialized memory contains a value that when reinterpreted as a pointer just happens to be a pointer to memory that is valid right now. On the other hand, it might point to truly invalid memory. If you use IsBadWritePtr to "validate" your pointers before writing to them, then in the case where it happens to point to memory that is valid, you end up corrupting memory (since the pointer is "valid" and you therefore decide to write to it). And in the case where it happens to point to an invalid address, you return an error code. In both cases, the program keeps on running, and then that memory corruption manifests itself as an "impossible" crash two hours later.

    In other words IsBadWritePtr is really CorruptMemoryIfPossible. It tries to corrupt memory, but if doing so raises an exception, it merely fails the operation.

    Many teams at Microsoft have rediscovered that IsBadXxxPtr causes bugs rather than fixes them. It's not fun getting a bucketful of crash dumps and finding that they are all of the "impossible" sort. You hunt through your code in search of this impossible bug. Maybe you find somebody who was using IsBadXxxPtr or equivalently an exception handler that swallows access violation exceptions and converts them to error codes. You remove the IsBadXxxPtr in order to let the exception escape unhandled and crash the program. Then you run the scenario again. And wow, look, the program crashes in that function, and when you debug it, you find the code that was, say, using a pointer after freeing it. That bug has been there for years, and it was manifesting itself as an "impossible" bug because the function was trying to be helpful by "validating" its pointers, when in fact what it was doing was taking a straightforward problem and turning it into an "impossible" bug.
    Ultima modifica di MItaly; 18-10-2014 a 18:53
    Amaro C++, il gusto pieno dell'undefined behavior.

  6. #6
    Quote Originariamente inviata da MItaly Visualizza il messaggio
    ...un crash immediato fa notare subito al programmatore che ha sbagliato ad usare la tua funzione.
    Esatto. La validità del puntatore fa parte del "contratto" tra la tua funzione e chi la richiama. Dal momento che, purtroppo, C e soprattutto C++ sono ben lungi dalla raffinata perfezione di Eiffel, bisogna accontentarsi di un supporto implicito e parziale ai contratti. Pertanto, chi richiama la funzione si assume la piena responsabilità di quel che passa come parametro, secondo l'infallibile regola aurea della programmazione procedurale "If you pass crap, all you will get is more crap". Dal canto tuo, come progettista di librerie e moduli, un bel crash immediato è il meglio che puoi offrire in risposta ad un uso inappropriato della funzione.

    Ben diverso è il discorso per la maggior parte delle funzioni della libreria standard, che nelle implementazioni mainstream vanno in crash anche per colpa di un banale puntatore NULL.
    Ultima modifica di M.A.W. 1968; 18-10-2014 a 19:16
    • Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.

  7. #7
    Utente di HTML.it
    Registrato dal
    Dec 2004
    Messaggi
    286
    Quote Originariamente inviata da oregon Visualizza il messaggio
    Puoi sempre far lavorare la funzione su una copia della stringa.
    Sinceramente fatico a capire; intendi creare una copia (statica) nel corpo funzione e restituirne il puntatore?

  8. #8
    Utente di HTML.it
    Registrato dal
    Dec 2004
    Messaggi
    286
    Quote Originariamente inviata da MItaly Visualizza il messaggio
    Meglio, un crash immediato fa notare subito al programmatore che ha sbagliato ad usare la tua funzione.
    Tu e M.A.W mi avete convinto che è meglio mantenere la funzione più "snella" e delegare la soluzione di questo tipo di problema ad una corretta pratica di programmazione.

    Solo a titolo di curiosità, mi è passato per la mente che si potrebbe verificare il valore del puntatore per escludere che punti ad una zona della memoria virtuale in cui risiedono i dati costanti (sola lettura).

    Il valore base predefinito di memoria RVA per il segmento .data dovrebbe essere 0x00400000, (eccetto per Windows CE). Per ottenere il valore di fine sezione potrei interrogare la struttura IMAGE_OPTIONAL_HEADER membro di IMAGE_NT_HEADERS restituita dalla funzine CheckSumMappedFile, ma purtroppo ora non ho il tempo per dedicarmi a questa curiosità.

  9. #9
    Quote Originariamente inviata da Paulin Visualizza il messaggio
    Sinceramente fatico a capire; intendi creare una copia (statica) nel corpo funzione e restituirne il puntatore?
    Il suggerimento del nostro ottimo Oregon verte su un template simile alla strdup() o funzioni analoghe. La funzione alloca (dinamicamente, o da un pool preallocato in heap) un buffer delle dimensioni desiderate, vi effettua le operazioni previste, e infine ne restituisce al chiamante il puntatore.

    Vantaggi: quasi nulli. Si evita il passaggio del puntatore come parametro e si elimina la remotissima possibilità di errore legata al misutilizzo di un puntatore a memoria non scrivibile.

    Svantaggi: notevoli. Quasi tutte le norme di stile deprecano la restituzione di puntatori, vieppiù allocati nel corpo di una funzione
    subordinata (che non sia banalmente parte della famiglia *alloc()). Nella maggior parte delle normative si raccomanda la restituzione di un valore booleano che indichi l'eventuale presenza di errori, mentre la restituzione di eventuali valori avviene tramite le metodologie standard: variabili static a livello di modulo o applicativo, passaggio di puntatori, stack o heap appositi.

    La robustezza delle funzioni, in casi come quello qui discusso, è strutturalmente legata alla prevenzione dell'uso di puntatori NULL. Da notare che tutti i migliori RTOS mettono a disposizione apposite API per la verifica dei permessi inerenti il segmento/pagina di memoria referenziato da un dato puntatore, data l'enorme varietà architetturale dei sistemi embedded (un attributo di pagina può anche essere modificato a runtime, ma su taluni tipi di memoria ROM la scrittura è fisicamente impossibile). Tali informazioni sono ottenibili, in modo maggiormente laborioso, anche sui SO mainstream.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.