Основной ответ:
Насколько я понимаю, вы хотите, чтобы arraynodes
удерживал для каждого индекса узла смещение в списке ребер, где начинаются ребра для этого узла.
Вы перебирайте список ребер, и каждый раз, когда изменяется начальная точка, вы сохраняете текущее смещение в arraynodes
Это ошибочно, потому что не все узлы являются отправной точкой ребра. Таким образом, если ваш список ребер имеет ребро от узла 5 -> 7, а затем ребро от 6 -> 7, вы зарегистрируете изменение начальной точки с 5 на 6, но вы сохраните текущее смещение в начале arraynodes
и не для 5-го узла.
Чтобы исправить это, вместо этого сделайте следующее: Сохраните смещение в списке ребер, изначально равное нулю. Выполните итерацию по узлам, для каждого узла сохраните текущее смещение в arraynodes
. Затем увеличивайте смещение до тех пор, пока начальная точка ребра при текущем смещении равна текущему узлу. Таким образом, arraynodes
сообщит вам для каждого индекса узла, в каком индексе в списке ребер хранятся ребра, начинающиеся в этом узле.
/**
* Assumption: Edges are sorted by their starting point.
*/
int edge_count = maxsize;
int edge_offset = 0;
/**
* For each node:
*
* - Store current edge_offset in arraynodes
* - Increment edge_offset as long as the start point
* of the edge at that offset matches the current node.
*/
for (int i = 0; i < nodes; i++) {
int current_node = map[i];
arraynodes[i] = edge_offset;
while (edge_offset < edge_count && array[edge_offset].start == current_node) {
edge_offset++;
}
}
/**
* Copy end-points of edges to arrayedges.
*
* You don't really need this, you could also directly
* access the end-points in your output loop ...
*/
for (int i = 0; i < edge_count; i++) {
arrayedges[i] = array[i].end;
}
Проблемы безопасности памяти:
Есть несколько проблем с безопасностью памяти в вашем коде:
- Переполнение буфера: при первом проходе l oop,
counter
равно нулю, поэтому map[counter-1]
выходит за пределы.
counter = 0;
int nodes = 10;
int *map = malloc(nodes * sizeof(int));
if (map == NULL) {
printf("Error allocating memory\n");
abort();
}
for (i = 0; i < maxsize; i++) {
if (map[counter - 1] == array[i].start)
continue;
Переполнение буфера: при инициализации карты вы хотите удвоить ее размер при заполнении. Однако в
mapdoublesize
, когда вы копируете данные со старой карты на новую карту, вы перебираете всю новую карту, поэтому вторая половина этого l oop читает за пределами старой карты:
nodes *= 2;
for (int i = 0; i < nodes; i++) {
new_array[i] = (*map)[i];
}
Переполнение буфера: в последней итерации этого l oop: Доступ к
array[i+1]
выходит за пределы:
for (i = 0; i < maxsize; i++) {
arrayedges[i] = array[i].end;
if (array[i].start != array[i + 1].start) {
Переполнение буфера: в ваших выходных данных l oop, если
i
является последним узлом, ваш доступ к
arraynodes[i+1]
выходит за пределы:
for (j = arraynodes[i]; j < arraynodes[i + 1]; j++) {
I не гарантирую, что я обнаружил все проблемы с безопасностью памяти. Вполне возможно, что еще. Я бы посоветовал вам улучшить структурирование и документирование вашей программы: разбейте вашу программу на более мелкие функции, которые выполняют один шаг, и документируйте предположения и предварительные условия этого шага (т.е. каковы границы массива, к которому вы обращаетесь?). Дайте имена переменных, которые четко описывают их назначение, не используйте переменные повторно. Это должно помочь вам обнаружить ошибки такого рода. Также я бы посоветовал вам использовать инструменты для проверки безопасности памяти. И G CC, и Clang имеют функцию ASAN, которая автоматически вставляет отладочный код в ваш двоичный файл, который будет обнаруживать и сообщать о проблемах безопасности памяти при запуске вашей программы. Вы можете включить это, скомпилировав с -fsanitize=address
( reference ). Другим инструментом с аналогичной областью применения будет Valgrind ( reference ). Эти программы, конечно, не могут найти все ошибки, так как они только динамически анализируют код, который фактически выполняется. Если в какой-то ветви вашей программы есть ошибка, которая не достигнута текущим исполнением, она не будет обнаружена. Таким образом, вы все еще не можете внимательно посмотреть на вашу программу.