Frage zu new/delete (C++)

OP #7486092
Lesenswert?

Hallo,

ich kann die Warnung beim Code unten (gegen Ende, bei "delete[] cells") nicht nachvollziehen. Der einzige Grund für eine fehlende Initialisierung von "cells" wäre doch eine Exception beim ersten new. Dann würde aber der Code im catch-Block gar nicht erreicht. Oder sehe ich das falsch?

1
int** alloc_cells(size_t rows, size_t columns)
2
{
3
  int** cells { new int* [rows] };
4
  
5
  size_t row_idx {};
6
  try {
7
    while (row_idx < rows) {
8
      cells[row_idx] = new int[columns];
9
      ++row_idx;
10
    }
11
  }
12
  catch (const std::bad_alloc&) {
13
    for (size_t remove_idx {}; remove_idx < row_idx; ++remove_idx) {
14
      delete[] cells[remove_idx];
15
    }
16
  
17
    delete[] cells; // Warning C6001: Using uninitialized memory 'cells'
18
    cells = nullptr;
19

20
    throw;
21
  }
22

23
  return cells;
24
}

Hinweis: Das ist eigentlich eine "Hilfs-Klassenfunktion" für eine kleine Übung aus einem Buch, bei der es um manuelles Speichermanagement geht; dass dies bei "richtigem" C++-Code nicht so gemacht werden sollte, ist mir klar (und wird auch explizit erwähnt). Ich habe als Typ oben der Einfachheit halber statt "SpreadsheetCell" int verwendet.

1
// Vorgegeben
2
class Spreadsheet
3
{
4
  ...
5
  SpreadsheetCell** m_cells { nullptr };
6
};
Moderator #7486178
Lesenswert?

Oliver S. schrieb:

„Die anderen“ sind bei der Warnung auch nicht ganz fehlerfrei. Das verhindern von false positives scheint nicht so trivial zu sein.

Ob eine Variable initialisiert ist oder nicht, ist nicht allgemein entscheidbar. g++ und clang gehen mit diesem Problem auf verschiedene Weise um:

g++ sagt "‘<variable>' may be used uninitialized", wenn er trotz durchgeführter Kontrolflussanalyse sich nicht absolut sicher ist, dass die Variable initialisiert ist. Das ist insbesondere dann der Fall, wenn die Initialisierung der Variable fehlt und eine Zuweisung nur bedingt erfolgt. Er verwendet das Wörtchen "may", um auf seine Unsicherheit hinzuweisen.

clang++ sagt "'<variable>' is uninitialized when used here", wenn er sich absolut sicher ist, dass die Variable uninitialisiert ist. Das ist immer dann der Fall, wenn die Initialisierung der Variable fehlt und keine Zuweisung (auch keine bedingte) vor der ersten Lesezugriff erfolgt. Dadurch kann es allerdings passieren, dass bei einer tatsächlich uninitialisierten Variable die Warnung ausbleibt.

Da er MS-Compiler mitunter auch dann warnt, wenn selbst ohne großartige Kontrolflussanalyse offensichtlich ist, dass die Variable initialisiert ist, wäre er gut beraten, seine Warnung "Using uninitialized memory '<variable>' etwas weniger strikt (bspw. mit einem "Possibly" davor) zu formulieren ;-)

OP #7486186
Lesenswert?

Danke für die Infos! Wenn das bei einem "richtigen" Projekt auftritt, könnte man - wenn sicher ist, dass dort kein Problem vorhanden ist - vielleicht so etwas machen(?)

1
#if defined(_MSC_VER)
2
#define MSVC_DISABLE_WARNING_UNINITIALIZED_MEMORY __pragma(warning(push)) \
3
__pragma(warning(disable: 6001))
4
#define MSVC_RESTORE_WARNINGS __pragma(warning(pop))
5
#else
6
#define MSVC_DISABLE_WARNING_UNINITIALIZED_MEMORY
7
#define MSVC_RESTORE_WARNINGS
8
#endif
1
...
2
MSVC_DISABLE_WARNING_UNINITIALIZED_MEMORY
3
  ...
4
MSVC_RESTORE_WARNINGS
(Firma: Torrox.de) #7487308
Lesenswert?

Sabi schrieb:

ich kann die Warnung beim Code unten (gegen Ende, bei "delete[] cells") nicht nachvollziehen.

cells hat einen definierten Wert, der Speicherbereich, auf den cells zeigt allerdings nicht. Die definierten Werte bekommt, cells erst in Zeile 8. Wenn in Zeile 8 eine Ausnahme auftritt, dann können noch einige Elemente von *cells nicht initialisiert sein. In der Ausnahmebehandlung wird dann delete auf nicht initialisierten Werten ausgeführt.

Ein Grund mehr, warum jedes Objekt maximal eine dynamische Resource verwalten sollte. Wenn Du cells durch einen std::vector ersetzt, ist das Problem schon gelöst.

Beitrag #7487517 wurde von einem Moderator gelöscht.
Beitrag #7490104 wurde von einem Moderator gelöscht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren