Доступ к памяти при отрицательных индексах массива в C ++ не возвращает мусор - PullRequest
0 голосов
/ 24 октября 2018

Я написал следующую программу для поиска конкретной строки в заданном массиве строк.Я сделал ошибку в функции поиска и написал i-- вместо i ++.

#include <iostream>
#include <string>
using namespace std;

int search(string S[], int pos, string s)
{
    for(int i=0; i<pos; i--) {
        cout << i << " : " << S[i] << "\n";
        if (S[i] == s) {
            cout << "Inside Return ->\n";
            cout << i << " / " << S[i] << " / " << s << "\n";
            return i;
        }
    }
    return -1;
}

int main()
{
    string S[] = {"abc", "def", "pqr", "xyz"};
    string s = "def";
    cout << search(S,2,s) << "\n";
    return 0;
}

Логически цикл представляет собой бесконечный цикл и не должен останавливаться, но я заметил, что условие if было истинным для каждого поиска, и функция вернула -1.

Я напечаталзначения и заметил, что значение S [-1] всегда совпадает с третьим аргументом, передаваемым функции (искомая строка), из-за чего цикл каждый раз возвращал -1.

Эточто-то делает g ++ или это связано с тем, как память выделяется для формальных аргументов функции?

Вывод приведенного выше кода -

 0 : abc
-1 : def
Inside Return ->
-1 / def / def

PS - я использую g ++(Ubuntu 7.3.0-27ubuntu1 ~ 18.04) 7.3.0

Редактировать -Я понимаю, что g ++ не проверяет границы, но меня заинтриговал тот факт, что значения S [-1] всегда былитак же, как с.Мне было интересно, есть ли какие-либо возможные теории для этого

1 Ответ

0 голосов
/ 24 октября 2018

Доступ за пределами границ - это неопределенное поведение.

Неопределенное чтение поведения - это не «мусор» или «segfault», это буквально что угодно.Чтение может путешествовать во времени и заставить код ранее в программе вести себя по-другому.Поведение программы от начала до конца совершенно не определяется стандартом C ++ всякий раз, когда происходит какое-либо неопределенное поведение.

В этом случае наивная сборка и ABI сообщают вам, что аргументы в «стеке» ввремя выполнения находится рядом с такими вещами, как аргументы функции.

Так что наивное переписывание вашего кода в сборку приводит к чтению отрицательных индексов из аргументов функции.

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

При компиляции без LTO или через границы динамической библиотеки выможет иметь некоторую уверенность в том, что опубликованный компилятором ABI будет использоваться для выполнения вызова;любое предположение в другом месте опасно плохо.И если вы компилируете без LTO и полагаетесь на него, теперь это означает, что вам придется проверять каждую сборку вашего кода с настоящего момента до вечности или рискнуть появиться ошибка без видимой причины в течение долгого времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...