Нужно использовать только первый метод. Второй метод это жутко грязный подход. Криминал. Расстрел.
Что касается вопроса о влияния значения
cElements в момент освобождения памяти — вопрос интересный. Сам процесс уничтожения массива нужно разделить на две фазы.
Первая фаза — это зачистка контента массива. Если это массив объектов, ссылки будут занулены, будет вызван IUnknown::Release. Если это строки, будет вызван SysFreeString для каждого элемента. VariantClear для вариантов. И тому подобное. На эту фазу, безусловно, значение
cElements влияет.
Вторая фаза — собственно освобождение региона памяти. Здесь нет однозначного ответа. Большинство реализаций кучи памяти имеет метод «free», который принимает только адрес блока, и не требует указывать размер. Менеджер кучи сам знает и ведёт учёт, какому блоку какой размер соответствует. Обычно этот размер хранится непосредственно перед самим блоком. Что касается массивов, созданных с помощью функций из
oleaut32.dll, то они используют
IMalloc::Alloc и
IMalloc::Free. Метод IMalloc::Free традиционно не принимает размер блока, а значит освободит именно тот блок, какой был выделен, ни байтом больше.
Другое дело, что функции
SaMap и
SaUnmap (а именно так я назвал функции в своих
кирпичах, отвечающие за проецирование SAFEARRAY-массива на произвольный регион памяти) обычно принимают ссылку на массив ByRef. При этом они не знают, кто является владельцем массива (владелец отвечает за создание и уничтожение). Они не знают, чем пользовался владелец для создания и выделения. Поэтому они не могут со стопроцентной уверенностью полагаться на то, что для освобождения памяти будет использован метод
IMalloc::Free.
С другой стороны, можно представить себе вилку вариантов: если
SaMap принимает массив ByRef, то значит есть VB-шная переменная-массив. Значит либо массив был выделен самим VB, либо остаётся вариант, что массив сконструировала третья сторона (возможно, пользуясь нестандартным способом управления памятью) и записала указатель на SA-дескриптор в VB-шную переменную. Но стоит помнить, что во втором случае автоматическое удаление массива силами VB пойдёт по сценарию oleaut32.dll, то есть память будет освобождена с помощью IMalloc:Free вне зависимости от того, как она была выделена. Так что если VB-шную переменную-массив устанавливает третья сторона, то и зачистку она должна делать. И с такими массивами не нужно использовать трюки с подменой cElements.