Как я могу повредить сегмент данных процесса Linux? - PullRequest
1 голос
/ 10 марта 2011

Я кодирую на C / C ++. Каковы возможные способы повреждения статической переменной, которая хранится в сегменте данных? Это считается утечкой памяти?

#include <stdio.h>

int aaa[5]; 
int bbb; 
int main() 
{ 
        int i; 
        bbb=41;
        for (i = 0; i < 6; ++i) 
                aaa[i] = 42; 
        printf("%d\n", bbb);
        return 0; 
} 

код выше печатает bbb = 42, а не 41. это возможная причина. Другой способ состоит в том, чтобы изменить статические данные доступны через несколько потоков.

Есть ли другие способы?

Ответы [ 5 ]

4 голосов
/ 10 марта 2011

Нет, это не утечка памяти. Утечка памяти - это когда вы выделяете в свободном хранилище (с malloc / new), а затем никогда не free / delete выделенный блок.

2 голосов
/ 10 марта 2011

Обратите внимание, что это неопределенное поведение и не гарантируется:

int bbb;
int aaa[5];
int main()
{
    int i;
    bbb=41;
    for (i = 0; i < 6; ++i)
            aaa[i] = 42;
    printf("%d\n", bbb);
    return 0;
}
g++ -o test test.cpp && ./test
41

В этом конкретном случае bbb хранится после aaa, но на это вообще не следует полагаться, потому что это может быть где-то еще.

1 голос
/ 31 августа 2013

Это типичная ошибка программирования. Вы определяете 5 элементов массива aaa, используя 6 aaa, что означает, что вы можете использовать только aaa [0], aaa [1], aaa [2], aaa [3] и aaa [4]. ааа [5] не определено. Это ошибка, ошибка программирования и больше ничего. Период.

1 голос
/ 10 марта 2011

Да, существует более одного метода для уничтожения содержимого глобальных переменных (ваши переменные не являются статичными в примере, который вы опубликовали) .

Указатели - хороший инструмент для повреждения памяти и записи там, где ваша программа не должна.Приведение может также добавить некоторое волнение:

#include <iostream>
using namespace std;

int aaa[5];
int bbb;

int main(void)  // Do *your* main() functions always return a value????
{
  double * ptr_double = 0;
  // Assign the pointer to double to point to the last integer.
  // Treat the last integer in the array as a double.
  aaa[4] = 45;
  cout << "aaa[4] = " << aaa[4] << endl;

  ptr_double = (double *)(&aaa[4]);
  *ptr_double = 3.14159267;
  cout << "aaa[4] = " << aaa[4] << endl;

  return -1;
}

При наличии нескольких потоков каждый поток может записать в глобальную переменную, а затем прочитать их обратно.Размещение случайных задержек до и после записи может показать вам более подробно, как это работает.

Другой метод - присвоить адрес вашей переменной регистру назначения аппаратного устройства ввода / вывода, например, UART.Когда UART получает данные, он помещает эти данные в эту переменную безотносительно к назначению переменной.

Обычно значения искажаются при записи кода в местоположение, которое не должно быть.Основной причиной является переполнение буфера: запись большего количества данных, чем выделено для переменной.Переполнения могут также происходить от аппаратных устройств, таких как контроллеры DMA и контроллеры USB.Другая причина - указатели: указатель указывает на неверное местоположение.

Переменные могут быть повреждены из-за переполнения стека и переполнения кучи.На многих архитектурах эти структуры расширяются навстречу друг другу.Слишком много переменных в стеке или рекурсии функций (или глубина вызова) могут перезаписать стек в кучу.Аналогично, выделение слишком большого количества памяти из кучи может привести к перезаписи кучи в стеке.

Вместо того, чтобы исследовать, как повредить переменные, я считаю, что вам следует поработать над повышением безопасности кода: спроектируйте и напишите свой код, чтобы в нем не было переполнений буфера, записи в правильные расположения и общие переменные были защищены от одновременной записи несколькимизадачи и темы.

1 голос
/ 10 марта 2011

Все глобальные переменные, статические или иные, инициализируются загрузчиком до значения, указанного в их объявлении (или нуля, если не указан), до выполнения какого-либо кода в процессе.Значения по умолчанию будут изменены только кодом, выполняемым в процессе (исключая любые внешние помехи от отладчика).

Если вы видите «поврежденное» значение в начале функции main() вашей программы,это, скорее всего, связано с неправильным действием, созданным в конструкторе глобального объекта C ++.Конструкторы для всех глобальных объектов C ++ запускаются до вызова main().

Самый простой способ отследить источник такого рода повреждений - это, вероятно, запустить процесс под отладчиком и установить точку наблюденияпо адресу глобальной переменной.Отладчик сломается, когда данные будут изменены.Скорее всего, у вас проблемы с переполнением массива или ошибкой указателя.Они могут быть сукой, чтобы выследить вручную.

...