Подаване на std::string в API на библиотека

В момента изграждаме API за определена библиотека. Част от интерфейса изисква библиотеката да получава и връща към потребителските класове като вектор и низ.

Когато се опитвате да симулирате използването на библиотеката в прост сценарий, в режим на отстраняване на грешки системата се срива при доставяне на низ като вход.

Вярвам, че има различно представяне на класа низ в режим на отстраняване на грешки или освобождаване. След това нашата библиотека приема да получи определено представяне, да прочете член на данните неправилно и да разруши по пътя. Кой е най-добрият метод за прехвърляне на STL обекти в API. Целевата операционна система е Windows XP, компилиран с MSVC 8, въпреки че потребителят на библиотеката ще използва Windows, техният компилатор може (и вероятно ще бъде) различен. Идеи, които имахме досега:

  1. Променете низа на char* - Но тогава разработчиците може да са объркани от отговорността за освобождаване на паметта.
  2. Използвайте нашата собствена версия на String – не искам да разработвам друга частна реализация на string.
  3. Пускане за потребителска версия за отстраняване на грешки и версия за освобождаване.
  4. Попитайте хората в Stack overflow за някоя опция, която пропускаме или не разбираме, или просто чуйте от техния опит - готово.

person Hagai    schedule 02.07.2010    source източник
comment
Вярвате ли, че има различно представяне или знаете, че има?   -  person    schedule 02.07.2010
comment
@Neil: добра гледна точка. Знаеш ли повече за това? Въпреки това, дори ако няма разлика между издание и отстраняване на грешки, все още е под въпрос използването на STL в API, използван от трети страни IMHO.   -  person lornova    schedule 02.07.2010
comment
И ако вашата библиотека получи обекта, който ще съдържа данни, които трябва да бъдат доставени. По този начин няма риск от освобождаване на данни от паметта.   -  person lsalamon    schedule 02.07.2010
comment
@Neil: Вярвам. Защото, ако конфигурацията на потребителския симулиращ код е пусната, всичко работи добре. Ако изчислите sizeof(String) в изданието и в конфигурацията за отстраняване на грешки, ще получите различни резултати.   -  person Hagai    schedule 02.07.2010
comment
Не казвате изрично каква операционна система и инструментална верига използвате. Всички се досещат, че това е Windows + VisualC++. Вероятно това е така, защото Windows има странна семантика за управление на паметта, когато започнете да използвате DLL файлове, и също така прави двоични файлове за отстраняване на грешки и освобождаване, които не са съвместими с връзки. Unix обикновено няма тези проблеми - със сигурност съм написал много библиотеки, които използват STL типове в API и никога не съм имал проблем. Така че може би трябва просто да изясните каква е вашата целева платформа.   -  person alex tingle    schedule 03.07.2010
comment
@alex tingle: Благодаря, изясних проблема във въпроса.   -  person Hagai    schedule 03.07.2010


Отговори (2)


Трябва да избягвате предаването на STL обекти между различни двоични модули.

За низ трябва да разчитате на const char* за параметър само за четене и char*, <buffer size> за входни параметри...

За векторите може да е малко по-трудно, особено ако трябва да промените съдържанието на вектора...

За вашите идеи:

  1. Вие сте прав, но конвенцията обикновено е, че не можете да съхранявате предадения указател (трябва да направите вашето локално копие).
  2. В крайна сметка ще имате същия проблем, освен ако нямате едно и също двоично представяне на версията за отстраняване на грешки и освобождаването на вашата реализация.
  3. Това може да е вредно, ако използвате различни версии/имплементация на STL в двата двоични модула (освен ако не сте сигурни, че потребителят на библиотеката ще използва същия STL).
person lornova    schedule 02.07.2010
comment
За гласуващите против: моля, добавете обяснителен коментар, за да разберем какво не е наред... - person lornova; 02.07.2010
comment
Моля, обяснете какво имате предвид под двоични модули. - person ; 02.07.2010
comment
@Neil: например .exe и .dll, или статично свързана библиотека, или като цяло всеки два компилирани модула, които ще бъдат свързани заедно. Ако използват различни реализации на STL... оппс. - person lornova; 02.07.2010
comment
@lorenzo предавам низове, вектори и т.н. към статични библиотеки през цялото време без проблеми. Разбира се, библиотеките трябва да бъдат компилирани със същия компилатор като изпълнимия файл, но същото би било вярно и за C кода, ако библиотеката и изпълнимият файл имат задължения за управление на споделената памет. - person ; 02.07.2010
comment
@Neil: Мислех, че C (не съм много сигурен пред C++) има двоично съответствие (между различни реализации) на ниво линкер, когато се използва същата конвенция за извикване. Вие сте почти верен за управлението на паметта: не можете да free памет с C библиотека, която е била разпределена с друга C библиотека, поради тази причина разпределителят на операционната система се използва при проектирането на библиотеки (поне в Windows). - person lornova; 02.07.2010
comment
@Lorenzo Не, няма стандарт за двоична съвместимост на C, въпреки че на повечето платформи има такъв по подразбиране. И когато проектирам библиотеки, обикновено не вземам предвид платформата, разбира се, не наричам неща като GlobalAlloc(). - person ; 02.07.2010
comment
Само за да разширим малко гледната точка на Лоренцо: трябва да проверите дали и двете използват точно едно и също копие за отстраняване на грешки или без отстраняване на грешки на DLL за изпълнение на C. Ако има несъответствие или са статични, тогава няма да работи. - person Rup; 02.07.2010
comment
@Neil: хм, прав си... C ABI съвместимостта всъщност се налага от ABI, използван от системни извиквания на конкретни платформи... - person lornova; 02.07.2010
comment
@Rup: точно, но ако проектирате библиотека, не трябва да принуждавате клиента да използва специфична реализация на STL... - person lornova; 02.07.2010
comment
@Лоренцо. Всъщност не - двоичният ABI се прилага (ако това е думата) от най-популярния компилатор и линкер. Системните повиквания (поне на Linux) всъщност се извикват чрез извикване на софтуерно прекъсване. - person ; 02.07.2010
comment
@Neil: Не се занимавам с ОС от шейсетте години :-) Шегата настрана, в Windows системните извиквания са C функции, така че конвенцията за извикване, използваща там, е де факто стандартният ABI (можете да спорите, че действителното системно извикване е извършено с извикване на syscall ASM дори в Windows, но разработчикът не трябва да се занимава с това). - person lornova; 02.07.2010
comment
@lorenzo UNIX е операционна система от 70-те, Windows е операционна система от 80-те и Linux е операционна система от 90-те. Освен това Windows всъщност не документира какво е и какво не е системно повикване, което обикновено се приема за превключване в режим на ядрото. Нищо от това няма нищо общо с C ABI, разбира се. - person ; 02.07.2010
comment
@lorenzo Ако предоставите двоична библиотека, трябва да принудите библиотеката да използва същата (не конкретна) реализация на стандартната библиотека като повикващия. - person ; 02.07.2010
comment
@Neil: UNIX е от 1969 г., а Linux е толкова подобен на UNIX, че не може да се счита за дизайн от 90-те. Въпреки това явно беше шега. - person lornova; 02.07.2010
comment
@Neil: документираният начин за извикване на системни услуги на Windows е да се използва Windows API, който е колекция от C функция. Конвенцията за извикване на тези C функции, плюс изискванията за подравняване, е де факто стандартът C ABI в Windows. - person lornova; 02.07.2010

Изобщо не е неразумно да карате хората да се свързват срещу отстраняване на грешки в режим на отстраняване на грешки и да освобождават в режим на освобождаване. Така го прави почти всяка библиотека. Дори огромни проекти като DirectX пускат компилации за отстраняване на грешки на своите двоични файлове. #3 е напълно разумен вариант/решение.

person Puppy    schedule 02.07.2010
comment
@Lorenzo: Вие използвате STL на вашия компилатор. Ако имате безплатен компилатор като GCC, тогава карате потребителите си да актуализират. Ако имате платен компилатор с повече версии като MSVC, просто компилирате срещу MSVC8,9,10. - person Puppy; 02.07.2010
comment
@DeadMG: но ако компилирате библиотеката си с даден компилатор, ако експортирате STL обекти, ще принудите потребителя на библиотеката да използва същата среда в нейното приложение. - person lornova; 03.07.2010
comment
@Lorenzo: Библиотеките така или иначе не са съвместими между процесори и други подобни. След като имате една и съща цел, не е неразумно да използвате същия компилатор. - person Puppy; 03.07.2010
comment
@DeadMG: Добре, значи аз съм доставчикът на библиотеката (предполагаме Windows и DLL) и избирам да използвам компилатор Intel C++ 10 и sgi STL. Клиентът няма да разбере каква библиотека и компилатор използвам, тъй като ще получи двоичния модул. Той ще използва MSVC 7 със стандартния STL. Моята библиотека експортира STL низ и вектори, съвместими ли са двете реализации? - person lornova; 03.07.2010
comment
@Lorenzo: Ето защо използвате мажоритарния компилатор за вашата платформа. MSVC Express е безплатен. - person Puppy; 03.07.2010