Форум: "Начинающим";
Текущий архив: 2009.11.01;
Скачать: [xml.tar.bz2];
ВнизНе пойму почему ошибка при SetLetngth Найти похожие ветки
← →
kostyl_kostyl (2009-09-15 17:55) [0]Не пойму почему ошибка при SetLetngth
Есть объект, у которого дискретно увеличиваются массивы свойствprocedure TMyObject.Add(NewValue: Integer);
var
L: Integer;
begin
L := length(Values);
if (L < Count + 1) then
begin
SetLength(Values, L + 10);
SetLength(OtherValues, L + 10);
SetLength(OtherOtherValues, L + 10);
end;
Values[Count] := NewValue;
Inc(Count);
end;
То есть три свойства это массивы и я выделяю постепенно память для них. Все одни синхронизированы, то есть всегда имеют одинаковую длину?
И вот SetLength(OtherValues, L + 10); происходит ошибка access violation read of adress...
Пробовал компилировать с {$R+}, все равно не пойму как понять почему такое бывает.
← →
palva © (2009-09-15 19:07) [1]Что такое массив свойств? Как в объекте описана Values?
← →
Сергей М. © (2009-09-15 21:37) [2]
> все равно не пойму как понять почему
Песня !
← →
Сергей М. © (2009-09-15 21:43) [3]
> SetLength(OtherValues, L + 10); происходит ошибка access
> violation
Костыль тут простой - кто-то или что-о загадило содержимое структуры, скрываемой за идентификатором OtherValues
← →
Rouse_ © (2009-09-15 23:22) [4]
> Есть объект, у которого дискретно увеличиваются массивы
> свойств
Зачем "дискретно" увеличивать три массива, представляющие данные по одному значению, вместо того чтобы представить эти три значения одной записью и плясать уже от массива оных?
← →
KilkennyCat © (2009-09-15 23:43) [5]последние две строчки тоже неплохо выглядят.
← →
Achpile (2009-09-15 23:46) [6]делаешь так:
type
TValue = record
Value,
OtherValue,
OtherOtherValue: integer;
end;
var
Values: array of TValue;
procedure Add(NewValue: TValue);
begin
SetLength(Values, Length(Values) + 1);
Values[High(Values)] := NewValue;
end;
И все... Чтобы обратиться к любому элементу класса делаешь так:
Values[i].Value
или
Values[1].OtherValue
Ну вообщем как-то так... i - это индекс элемента, к которому хочешь обратиться...
← →
Rouse_ © (2009-09-15 23:59) [7]
> KilkennyCat © (15.09.09 23:43) [5]
>
> последние две строчки тоже неплохо выглядят.
Нормально выглядят, там же проверка выше :)
Тут Сергей прав - где-то засираются указатели...
← →
Германн © (2009-09-16 00:42) [8]Лично я вообще ничего не понял из сабжа. Кроме того, что приведенный код даёт ошибку.
← →
KilkennyCat © (2009-09-16 05:14) [9]
> Rouse_ © (15.09.09 23:59) [7]
нормально, но странно: я все жду, когда начнется использоваться параметр процедуры, и опа! в конце, да и так, невлиятельно.
← →
Achpile © (2009-09-16 06:58) [10]Мне интересно, почему прибавляется 1 элемент, а длина массива увеличивается на 10...
← →
MBo © (2009-09-16 08:24) [11]>Achpile © (16.09.09 06:58) [10]
Чтобы реже делать реаллокацию памяти
← →
Anatoly Podgoretsky © (2009-09-16 11:44) [12]> Achpile (16.09.2009 06:58:10) [10]
С этим полный порядок, проверка на наличие места в массиве.
← →
Anatoly Podgoretsky © (2009-09-16 11:45) [13]> MBo (16.09.2009 08:24:11) [11]
Лучше ее делать пропорционально, как в TList
← →
kostyl_kostyl (2009-09-16 12:36) [14]
> Костыль тут простой - кто-то или что-о загадило содержимое
> структуры
Вот я тоже так думаю, но как это можно сделать? Вот в чем вопрос.
Может эта бяка происходит когда я пишу и читаю OtherValues? Может например я делаю SetLength(OtherValues, 20); а где то пишу или читаю OtherValues[22]?
← →
Сергей М. © (2009-09-16 12:50) [15]
> как это можно сделать?
Вариантов нагадить существует множество.
Свой ты не показал)
> Может ..я делаю SetLength(OtherValues, 20); а где то пишу или читаю
> OtherValues[22]
Не может.
Исключение бы совсем другое было.
← →
kostyl_kostyl (2009-09-16 13:02) [16]
> Исключение бы совсем другое было.
ну да, тогда бы индекс за пределы вышел бы...
> Свой ты не показал
Ну так а как я чтением/записью могу испортить память? Размер я меняю только в одном месте, а остальные операции только чтение/запись?
← →
Сергей М. © (2009-09-16 13:07) [17]Чтением, конечно, не испортишь.
А записью запросто можно.
Причем испортить можно даже не обращаясь к этому полю, а обращаясь к вышефигурирующим полям того же объекта.
← →
kostyl_kostyl (2009-09-16 13:28) [18]
> Сергей М. © (16.09.09 13:07) [17]
А как же записью? Я же просто в ячейку по адресу пишу значение и всё? Или там типа конкуренция за область памяти какая то происходит?
← →
Сергей М. © (2009-09-16 13:39) [19]
> там типа конкуренция за область памяти какая то происходит?
О "конкуренции" можно говорить только в мультипоточном приложении.
А поскольку ты о мультипоточности своего приложения ничего не сказал, то и конкуренции никакой быть не может.
> Я же просто в ячейку по адресу пишу значение и всё?
Я не знаю, что ты там и куда пишешь, но вот тебе пример:TMyObject = class(..)
..
SomeField1, SomeField2: Чего-то_там;
OtherValues: array of Integer;
..
end;
..
//гадим в поле OtherValues, не обращаясь к нему явно ни по чтению ни по записи
Move(SomeField1, SomeField2, SizeOf(Чего-то_там) + 1);
← →
kostyl_kostyl (2009-09-16 14:22) [20]
> Сергей М. © (16.09.09 13:39) [19]
> //гадим в поле OtherValues, не обращаясь к нему явно ни
> по чтению ни по записи
Тю, а как за этим следить и как это вообще происходить может?
← →
Сергей М. © (2009-09-16 14:32) [21]
> как за этим следить
Ну как ? Глазами и головой, как же еще ?)
> как это вообще происходить может?
В смысле ?
Как умудриться сделать ошибку в своем коде что ли ?
← →
kostyl_kostyl (2009-09-16 14:46) [22]
> Сергей М. © (16.09.09 14:32) [21]
я просто из вашего примера не понял как портиться OtherValues? как это "внутри" просиходит?
← →
Сергей М. © (2009-09-16 15:15) [23]
> как это "внутри" просиходит?
Оч просто.
Для наглядности:
Пустьtype Чего-то_там = byte;
Пусть адрес поля SomeField1 в памяти приложения равен 100
Тогда адрес поля SomeField1 будет равен 100 + SizeOf(byte) = 100 + 1 = 101, а адрес поля OtherValues будет равен 100 + SizeOf(byte) + SizeOf(byte) = 100 + 1 + 1 = 102
Пусть ожидаемое корректное значение поля OtherValues равно 1, т.е. "единица" хранится в младшем байте этого поля, имеющем адрес 102.
Пусть в поле SomeField1 хранится значение 3, а в поле SomeField2 - значение 4.
Процедура Move(), вызываемая якобы для копирования данных из поля SomeField1 в поле SomeField2, ошибочно запишет 2 (!!!) байта данных в область памяти, начинающуюся с адреса 101 и заканчивающуюся адресом 102, т.е. "зацепит" данные в поле OtherValues, в результате чего значение поля OtherValues изменится и станет равным 4, хотя явных обращений к этому полю не было и было бы справедливо ожидать в нем значение 1.. если бы не ошибочный вызов Move(), "загадивший" это поле.
← →
Сергей М. © (2009-09-16 15:16) [24]
> Пусть адрес поля SomeField1 в памяти приложения равен 100
>
> Тогда адрес поля SomeField2
← →
kostyl_kostyl (2009-09-16 15:51) [25]а, понятно, но я не делаю подобных операций просто пишу/читаю в/из ячейки integer переменную integer и за length массивов не выхожу(тогда бы, как уже указывали, был бы другой эксцепшн). Еще примечательно то, что эта ошибка при одном и том же ходе программы, может возникать, а может и не возникать....
Ух...((( замаялся я уже ((
← →
Сергей М. © (2009-09-16 16:05) [26]
> я не делаю подобных операций
Ну другие какие-то делаешь, смысл от этого не меняется - поле-то испорчено у тебя ..
← →
sniknik © (2009-09-16 16:09) [27]имхо, это неуважение и оскорбление отвечающих, которым приходится "выпрашивать" проблемный код. нет так нет, на нет и суда нет. и ветки нет.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2009.11.01;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.089 c