C++ Почему этот массив, переданный по ссылке, генерирует ошибку времени выполнения?

void pushSynonyms (string synline,  char  matrizSinonimos [1024][1024]){


             stringstream synstream(synline);

             vector<int> synsAux;


             int num;

             while (synstream >> num) {synsAux.push_back(num);}


             int index=0;
             while (index<(synsAux.size()-1)){

                   int primerSinonimo=synsAux[index];
                   int segundoSinonimo=synsAux[++index];
                   matrizSinonimos[primerSinonimo][segundoSinonimo]='S';
                   matrizSinonimos [segundoSinonimo][primerSinonimo]='S';

                   }

           } 

и звонок ..

char matrizSinonimos[1024][1024];
     pushSynonyms("1 7", matrizSinonimos)

Мне важно передать matrizSinonimos по ссылке.

Обновлено: убрал & из &matrizSinonimos.

Обновлено: ошибка времени выполнения:

An unhandled win32 exception occurred in program.exe [2488]![alt text][1]

Какую ошибку это дает?

James Curran 22.01.2009 19:59

Необработанная исключительная ситуация win32 в program.exe [2488]

andandandand 22.01.2009 20:04

Вы знаете, где именно он вылетает? Индексы в диапазоне?

jpalecek 22.01.2009 20:07

Он вылетает при вызове функции, при извлечении matrizSinonimos он снова работает нормально.

andandandand 22.01.2009 20:11

Что такое полная ошибка времени выполнения? Включите материал в замещающий текст, что бы это ни было.

MSN 22.01.2009 21:56

какое сообщение об ошибке после того, как вы убрали "&" при передаче?

Johannes Schaub - litb 22.01.2009 22:05

Вы запускали это в отладчике? Если да, то на какой строке он находится при сбое и каковы значения index, primerSinonimo и segondoSinonimo? (И если вы не запускали отладчик, сделайте это.)

Kristopher Johnson 22.01.2009 22:32

о, никогда не упоминалось. Я думал, что у вас есть "&" при передаче.

Johannes Schaub - litb 22.01.2009 22:33
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
1 151
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Массивы передаются как указатели - нет необходимости передавать на них ссылку. Если вы заявляете, что ваша функция:

void pushSynonyms(string synline, char matrizSinonimos[][1024]);

Ваши изменения в массиве сохранятся - массивы никогда передаются по значению.

Когда у вас есть matrizSinonimos [1024] [1024] в параметрах вашей функции ar в качестве переменной внутри main (), вы выделяете 1 МБ памяти в стеке. Стек обычно большой, но он чрезмерный. Объявите фактический массив статическим и передайте указатель.

user3458 22.01.2009 20:19

@Arkadiy: Я пробовал: 'char static matrizSinonimos [10] [10]; char указатель = & matrizSinonimo; ' Ошибка компиляции: невозможно преобразовать char [] [10] [10] в char при инициализации.

andandandand 22.01.2009 20:51

Однако в списках параметров Harper, char matriz Sinonimos [1024] [1024] и char matriz Sinonimos [] [1024] одинаковы. Я должен вас неправильно понять.

Johannes Schaub - litb 22.01.2009 22:01

@dmindreader: char foo [10] [10] не является символом *, это символом **. Если вы хотите передать массив с этим синтаксисом, вы должны объявить: void pushSynonyms (string synline, char ** matrizSinonimos); . Обычно объявление с элементом-указателем принимает параметры длины для каждого измерения, чтобы избежать ошибок.

Harper Shelby 22.01.2009 22:13

"char * указатель = & matrizSinonimo;" не годится. Вам действительно нужно узнать, как многомерные массивы представлены в C. x [10] [10] - это не указатель на char, это указатель на массив блоков по 10 символов в каждом. Используйте char ptr [] [10] = matrix; «ptr» здесь - указатель на неопределенное количество блоков из 10 символов.

user3458 22.01.2009 22:25

(упс, «это указатель на массив блоков по 10 символов каждый» следует заменить на «это массив блоков по 10 символов в каждом»)

user3458 22.01.2009 22:26

(редактировать 1) Я забыл ответить на ваш актуальный вопрос. Что ж: после того, как вы исправили код, чтобы передать массив правильным образом (больше нет неправильного косвенного обращения), мне кажется наиболее вероятным, что вы неправильно проверили свои входные данные. Вы читаете из потока, сохраняете его в векторе, но никогда не проверяли, действительно ли все числа, которые вы получаете, находятся в правильном диапазоне. (конец редактирования 1)

Первый: Использование необработанных массивов может быть не тем, что вам нужно. Есть std::vector или boost::array. Последний представляет собой массив фиксированного размера времени компиляции, такой как необработанный массив, но предоставляет определения типов и методы коллекции C++, которые практичны для универсального (читай: шаблонного) кода.

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

Второй: Массивы передаются как указатели, сам указатель передается по значению.

В третьих: Такие большие объекты следует размещать в куче. Накладные расходы на выделение кучи в таком случае незначительны, и это уменьшит вероятность нехватки места в стеке.

Четвертый:

void someFunction(int array[10][10]);

на самом деле:

(редактировать 2) Спасибо за комментарии:

void someFunction (int ** массив);

void someFunction(int (*array)[10]);

Надеюсь, я не облажался в другом месте .... (конец редактирования 2)

Информация о типе массива 10x10 теряется. Чтобы понять то, что вы, вероятно, имели в виду, вам нужно написать:

void someFunction(int (&array)[10][10]);

Таким образом, компилятор может проверить, действительно ли массив на вызывающей стороне является массивом 10x10. Затем вы можете вызвать функцию следующим образом:

int main() {
  int array[10][10] = { 0 };
  someFunction(array);
  return 0;
}

void someFunction (int array [10] [10]) действительно void someFunction (int ( array) [10]). Вы можете проверить это с помощью MSVC или онлайн-компилятора C++ Comeau.

MSN 22.01.2009 21:52

вы оба неправы. void someFunction (int array [10] [10]); является недействительным someFunction (int (массив) [10]); :) gimpf ваш ответ был совершенно правильным, пока вы не сказали «void someFunction (int array [10] [10]); действительно void someFunction (int * array); "

Johannes Schaub - litb 22.01.2009 22:04

Исключением, вероятно, является 0xC00000FD или переполнение стека!

Проблема в том, что вы создаете в стеке массив размером 1 МБ, который, вероятно, слишком велик.

Ответ принят как подходящий

Что с этим не так

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

(synsAux.size()-1)

Он вычитает единицу из 0u. Это будет продолжаться, потому что size() возвращает беззнаковый целочисленный тип. В итоге вы получите очень большое значение, где-то около 2 ^ 16 или 2 ^ 32. Вы должны изменить все условие while на

while ((index+1) < synsAux.size())

Вы можете попробовать поискать ошибку на стороне вызова. Часто бывает, что где-то до этого происходит переполнение буфера или повреждение кучи, и в результате этого на более позднем этапе программы происходит сбой.

Аргументы и параметры в нем

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

char matrizSinonimos[1024][1024];

Двумерный массив на самом деле представляет собой массив массивов. Первый элемент этого массива - это массив, а указатель на него - это указатель на массив. В этом случае это

char (*)[1024]

Несмотря на то, что в списке параметров вы сказали, что принимаете массив массивов, компилятор, как всегда, корректирует это и делает его указателем на первый элемент такого массива. Итак, на самом деле ваша функция имеет прототип после того, как компилятор настроил типы аргументов:

void pushSynonyms (string synline,  char (*matrizSinonimos)[1024]);

Хотя часто предлагается, Вы не можете передать этот массив как char**, потому что вызываемой функции требуется размер внутреннего измерения, чтобы правильно адресовать подразмеры при правильных смещениях. Работая с char** в вызываемой функции, а затем записывая что-то вроде matrizSinonimos[0][1], он попытается интерпретировать первые символы sizeof (char **) этого массива как указатель и попытается разыменовать случайную ячейку памяти, а затем сделает это во второй раз, если между ними не произойдет сбой. Не делай этого. Также не имеет значения, какой размер вы указали во внешнем измерении этого массива. Это рационализировало. Теперь передавать массив по ссылке не очень важно. Но если вы хотите, вы должны все изменить на

void pushSynonyms (string synline,  char (&matrizSinonimos)[1024][1024]);

Передача по ссылке не передает указатель на первый элемент: все размеры всех измерений сохраняются, и передается сам объект массива, а не значение.

Это здорово, но это не совсем касается сбоя, который происходит на сайте вызова функции.

MSN 22.01.2009 22:23

Я думаю, ему лучше сосредоточиться на коде, связанном с вызовом. Я думаю, что ошибка может быть вызвана переполнением буфера или чем-то подобным.

Johannes Schaub - litb 22.01.2009 22:38

попробуйте объявить это как:

void pushSynonyms (const string & synline,  char  *matrizSinonimos[1024] )

Я верю, что это сделает то, что вы хотите. То, как у вас это есть, как говорили другие, создает в стеке массив размером 1 МБ. Кроме того, изменение синлайн с string на const string & исключает помещение полной копии строки в стек.

Кроме того, я бы использовал какой-то класс для инкапсуляции matrizSinonimos. Что-то вроде:

class ms
{
    char m_martix[1024][1024];
    public:
    pushSynonyms( const string & synline );
}

тогда вам вообще не нужно его сдавать.

Я не понимаю, что не так с приведенным выше кодом, но если вы не можете заставить синтаксис массива работать, вы всегда можете сделать это:

void pushSynonyms (string synline,  char  *matrizSinonimos, int rowsize, int colsize )
{
   // the code below is equivalent to 
   // char c = matrizSinonimos[a][b];
   char c = matrizSinonimos( a*rowsize + b );
   // you could also Assert( a < rowsize && b < colsize );
}

pushSynonyms( "1 7", matrizSinonimos, 1024, 1024 );

Вы также можете заменить rowize и colsize на #define SYNONYM_ARRAY_DIMENSION 1024, если он известен во время компиляции, что ускорит шаг умножения.

Другие вопросы по теме