Ошибка нарушения доступа при добавлении времени к строке в c ++ - PullRequest
4 голосов
/ 26 января 2012

Возьмите следующий код:

#inlcude <iostream>
#include <time.h>
using namespace std;

int main(int argc, char* argv[])
{
    time_t t;
    time(&t);

    string s = "file" + t;
    return 0;
}

На линии

string s = "file" + t

Я получаю ошибку нарушения доступа.

Если я изменю это на что-то вроде: #inlcude используя пространство имен std;

int main(int argc, char* argv[])
{
    time_t t;
    time(&t);
    int x = t;

    string s = "file" + x;
    return 0;
}

Я все еще получаю ту же ошибку. Как жизнь? Конечно, добавление int к строке не может вызвать нарушение прав доступа?

Ответы [ 3 ]

5 голосов
/ 26 января 2012
"file" + t

Это совсем не то, что вы ожидаете. "file" - массив символов. Вы не можете добавить целое число в массив символов. Но вы можете добавить целое число к указателю, и массивы неявно преобразуются в указатели. Значение t, вероятно, где-то в миллиардах. Таким образом, результатом "file" + t является некоторый указатель на миллиард или около того байтов от массива char "file". Затем вы пытаетесь инициализировать строку с этим указателем. Маловероятно, что у вас есть законный доступ к этой ячейке памяти, поэтому вы получаете нарушение прав доступа. Это неопределенное поведение в любом случае. Если бы вы сделали это:

std::string s("file");
s += t;

Вы бы получили правильную ошибку компилятора. Попробуйте вместо этого:

std::string s("file");
s += std::to_string((long long)t);

Если эта функция недоступна для вас (она нова в C ++ 11), вы можете использовать строковые потоки:

std::ostringstream oss;
oss << "file" << t;
std::string s(oss.str());
2 голосов
/ 26 января 2012

Проблема в том, что ваши строки не являются строками.

Вы должны помнить, что строковые литералы (вида "foo" не имеют типа std::string, но const char* (на самом деле они имеют тип const char[N], но для наших целей мы можем считать их указателями ).

Итак, когда вы пишете такой код:

std::string foo = "bar" + 42

тогда типы включаются следующим образом:

std::string = const char* + int

Другими словами, ваш код добавляет целое число к указателю, а затем результирующий указатель char сохраняется в виде строки.

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

Если мы сделаем это вместо:

std::string foo = std::string("bar") + 42

Затем мы создаем правильную строку, а затем пытаемся добавить 42 к этому. Это не определено, поэтому мы получим ошибку компилятора (что, по крайней мере, лучше, чем молча делать неправильные вещи).

Правильным решением является использование потока, как показано в одном из других ответов:

std::ostringstream os("file");
os << x;
std::string s = os.str();
2 голосов
/ 26 января 2012

Это не стандартный способ добавления целого числа к строке. C ++ представляет строку как указатель на массив символов. Добавляя к этому целое число, вы фактически увеличиваете указатель на блок памяти, который может не принадлежать вам. Исследуйте использование sprintf () для того, что вам нужно.

...