Forum: PC-Programmierung existierenden pointer auf NULL setzen


von Chandler B. (chandler)


Lesenswert?

Guten morgen,
ich soll unittests schreiben, habe aber bei einer bedingung ein Problem.
Folgende funktion:
1
void handleReceive(void)
2
{
3
  uint8_t *header;
4
  header = NULL;
5
6
  removeReceive(cid_b, &(header), &(length), &is_valid);  // hier wird header gesetzt
7
  if(NULL != header)
8
  {
9
    data = header;
10
    MessageReceive(data, length); // Diese Funktion ist gemockt
11
12
    if(NULL != data )
13
    {
14
      // mache etwas
15
    }
16
    else
17
    {
18
      // mache etwas anderes
19
    }
20
  }
21
}

Mein Problem ist die bedingung
if(NULL != data)
hier bekomme ich es nicht hin, dass data=NULL ist, da es ja quasi vorher 
schon abgefragt worden ist (NULL != header und data = header).
Jetzt habe ich versucht data in der Funktion MessageReceive zu löschen
1
void mockMessageReceive(uint8 *buffer, uint16 lenght)
2
{
3
//  buffer= NULL;
4
5
//  delete buffer;
6
7
//  uint8 *pointer;
8
//  pointer = NULL;
9
//  buffer = pointer;
10
11
  free(buffer);
12
13
  printf("buffer: %p\r\n", &buffer);
14
}
Allerdings bekomme ihc es nicht hin buffer zu löschen, bzw. buffer auf 
NULL zu setzen.

von Mike R. (thesealion)


Lesenswert?

Das geht auch so nicht. (Außer data wäre eine globale Variable und das 
ist hoffentlich nicht der Fall)

Ansonsten mach dir die Übergabe Typen (Call-by-Value und 
Call-by-Reference) klar.
Dann siehst du, dass die Abfrage
1
if(NULL != data )
in deinem Code nie falsch sein kann.

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Wie sieht die Signatur des Originals MessageReceive() aus?

Wenn das die gleiche ist wie bei mockMessageReceive(), dann kann die 
Funktion/Methode buffer bzw. data nicht geändert zurückgeben. Damit ist 
Test if(NULL != data ) überflüssig.

von BeBe (Gast)


Lesenswert?

Wo ist data definiert? Globale Variable?

So wie das programmiert ist, könnte die Verzweigung Toter Code sein 
(wenn die globale Variable nicht durch andere Codeteile verändert werden 
kann).

Für toten Code kann man keine Tests durchlaufen lassen. Das geht nur per 
Analyse.

von A. S. (Gast)


Lesenswert?

Das ist ein Dilemma. Machst Du die Frage weg, wird das bei der nächsten 
Änderung durchgehen.

Also brauchst Du statt if ein Konstrukt, dass als Zusicherung aktiv 
bleibt aber nicht als zu durchlaufender Zweig zählt.

Eine Art assert, dass eine Warnung verursacht, wenn es auftreten kann.

Den Code zu durchlöchern ist hingegen kontraproduktiv.

von Oliver S. (oliverso)


Lesenswert?

Hannes J. schrieb:
> Damit ist
> Test if(NULL != data ) überflüssig.

Und daher ist es auch irgendwie sinnfrei, darauf zu zu unit-testen.

Chandler B. schrieb:
> free(buffer);

Da sitzt das Problem. data kann zwar nicht NULL werden, aber auf einen 
nicht mehr gültigen Datenblock zeigen.

Oliver

: Bearbeitet durch User
von A. S. (Gast)


Lesenswert?

Chandler B. schrieb:
> MessageReceive(data, length); // Diese Funktion ist gemockt

na, dann mock halt per #define und setze data auf 0.

aber wie gesagt, befasse Dich lieber mit statischer Code-Analyse statt 
"100% getestet, also alles OK".

von MaWin (Gast)


Lesenswert?

Dass ein Codepfad tot ist und damit sinnlos und nicht testbar, ist das 
Ergebnis deines Tests.
Dieser Pfad kann also in der nächsten Version des Codes entfernt werden.

von A. S. (Gast)


Lesenswert?

MaWin schrieb:
> Dieser Pfad kann also in der nächsten Version des Codes entfernt werden.

Wie stelle ich sicher, dass dieser Zweig auch "tot" bleibt?

Also wie ist das Konstrukt einer Sicherheitsabfrage, die nie zuschlagen 
soll?

von doppelt hält besser (Gast)


Lesenswert?

Man kann doch einen Zeiger in der Funktion auf Null setzten, wenn man 
mit einem Doppelzeiger arbeitet.

Dann ist er auch außerhalb der Funktion NULL.
1
void
2
my_free (void** pp)
3
{
4
   free (*pp);
5
   *pp = NULL;
6
}
7
8
int
9
main (void)
10
{
11
   char* str = malloc (sizeof (*str) * 128);
12
   strcpy (str, "hi, there");
13
14
   puts (str);
15
   my_free ((void**)&str);
16
17
   // geht, da NULL
18
   free (str);
19
   free (str);
20
   free (str);
21
22
   return EXIT_SUCCESS;
23
}

von Oliver S. (oliverso)


Lesenswert?

doppelt hält besser schrieb:
> Man kann doch

Man kann sicherlich alles mögliche, aber im Code oben steht halt die 
Funktion

Chandler B. schrieb:
> MessageReceive(data, length); // Diese Funktion ist gemockt

und die kann data nicht verändert.

Die einzige Möglichkeit, data auf NULL zu bekommen, wäre über einen 
amoklaufenden Parallel-Thread, der den Datenbereich überschreibt. Ob man 
daraf testen will oder gar muß, muß der TO selber wissen.

Oliver

von doppelt hält besser (Gast)


Lesenswert?

Chandler B. schrieb:
> uint8_t *header;
>   header = NULL;
>   removeReceive(cid_b, &(header), &(length), &is_valid);  // hier wird
> header gesetzt

Da wird ja der Doppelzeiger benutzt.

Man muss halt auch bei der zweiten Funktion genauso arbeiten.

die Frage ist ja sowieso woher diese Variable "data" kommt. Vielleicht 
ist die Variable ja sogar global.

von doppelt hält besser (Gast)


Lesenswert?

Chandler B. schrieb:
> unittests

suggeriert ja auch dass der Code nicht untouchable ist.  Also die erste 
Stelle zum Verbessern gefunden.

von MaWin (Gast)


Lesenswert?

A. S. schrieb:
> Wie stelle ich sicher, dass dieser Zweig auch "tot" bleibt?

assert()

Wenn der echte Code allerdings nicht deutlich komplexer ist, als der 
gezeigte Code, sehe ich keinen Sinn in dieser Abfrage.
Sogar ganz im Gegenteil. Die zusätzliche Abfrage verkompliziert den 
Code. Die Lesbarkeit wird verschlechtert und somit wird die 
Fehleranfälligheit erhöht.

Ich würde den Pfad also ersatzlos streichen oder höchstens durch ein 
assert() ersetzen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.