Пусть ваша DLL экспортирует такую функцию:
Function Foo( _
ByVal Buffer As WString Ptr, _
ByVal Length As Integer _
)As Boolean
' Что‐то делаем:
Dim res As Boolean = Initialize(...)
If res = False Then
Return False
End If
' Работаем с буфером
write(Bufer, Length, ...)
Return True
End FunctionСоглашение по вызову просто: функция вернула True — значит, она завершилась успешно и вы можете использовать данные в Buffer. Если же функция вернула False, то она завершилась ошибкой, и значение Buffer не определено. Казалось бы, простое и логичное правило: что тут может пойти не так?
Дело в том, что проверять результат работы функции — это же куча работы. Люди ленивы. Поэтому они могут заметить, что ваша функция не трогает буфер, если она завершается неудачей. И они могут написать код вроде такого:
var buf = CAllocate(Length)
' Вызываем функцию из DLL
Foo(buf, Length)
' Выводим результат
PrintBuffer(buf, Length)
' Очистка
Deallocate(buf)В этом куске кода подразумевается, что если функция Foo завершится неудачно, то в buf будут нули, ведь он не тронут. Нули — это допустимое значение для нуль-терминированных строк, поэтому мы просто продолжаем выполнение (функция PrintBuffer).
Но нигде в контракте функции Foo об этом не сказано, поэтому это — деталь реализации. И однажды в новой версии DLL (и функции Foo) вы используете буфер buf для промежуточных вычислений. Вам нужен кусок памяти, и тут как раз он без дела болтается, так что вы используете его. Вы имеете полное право на это, вы всё делаете правильно:
Function Foo( _
ByVal Buffer As WString Ptr, _
ByVal Length As Integer _
)As Boolean
' Используем буфер для промежуточных вычислений
Calculate(Buffer, ...)
' Что‐то делаем:
Dim res As Boolean = Initialize(...)
If res = False Then
Return False
End If
' Работаем с буфером
write(Bufer, Length, ...)
Return True
End FunctionОднако когда вы установите на машину клиента новую версию своей DLL, тогда перестанет работать установленная программа другого человека, который использовал вашу DLL:
var buf = CAllocate(Length)
' Вызываем функцию из DLL
Foo(buf, Length)
' Выводим результат
' Получаем мусор на выходе — программа перестала работать
PrintBuffer(buf, Length)
' Очистка
Deallocate(buf)Вина ваша? Нет. Но что скажет пользователь? «Не ставьте новую версию «Ваш Продукт» — он ломает «Программу Другого Человека»!» или: «Проклятый DLL Hell, проклятый Microsoft и проклятый Билл Гейтс!» или просто: «Компьютеры такие глупые! Их так тяжело использовать!»