LINUX.ORG.RU

Чем чреват и плох подобный код на практике?

 ,


0

1
extern "C"
{
    QString boo()
    {
        return "9";
    }
}

Да-да, я в курсе, что оно вообще не должно работать, но оно линкуется с эльфом и работает. Вопрос в том, каковы пределы, за которыми реально выстрелы в ногу ещё не начнут происходить? Те подводные камни, которые приходят в голову в первую очередь, не пугают, но может кто ещё интересного что подскажет?

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 1)

clang об этом предупреждает

xpahos ★★★★★
()

Два момента:

  1. Простой = компилятор не будет декорировать имя функции.

  2. Не простой = Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementation-defined and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved.

Из второго следует, что это UB в случае если результат или аргументы такой С++ функции не являются POD-ами. Иначе говоря, в C++ для нет POD-типов может быть не такое ABI, как в C.

Deleted
()

Чем чреват и плох подобный код на практике?

Придёт царь и умножит тебя на ноль.
А если серьёзно, то явное лучше не явного и не надо дёргать компилятор за яйца.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 1)

Спроси у своего руководителя практики.

anonymous
()

В таком простом примере приходит на ум только, что перегрузка не будет работать и то в данном случае не суть как уместно.

Было бы прикольно посмотреть на выхлоп nm для этой функции.

pon4ik ★★★★★
()

Тем что кто это будет читать зависнет =) Потом отвиснет побоится показаться дураком и начнёт подобное использовать, потом таких людей наберётся пару сотен, затем новичёк встретит такой код ничего не поймёт и напишет на стаковерфлов и к его несчастью ему ответят 10 человек из этих сотен что подобная практика довольно часто им встречалась и следовательно это всё нормально. Затем кто-то напишет на говнокод, а человек с большой чуйкой отретраслирует это на реддит после чего там разгорится холивар который заметят на опеннете потом там будет холивар, затем один из лоровцев скопипастит тему на лор, а другой лоровец найдёт эту тему взаржот и распространит инфу она попадёт опять на реддит и прочие ресурсы включая говнокод, про тебя напишут на лурке и закидают помидорками, а на лоре будут тролить. Так что

Чем чреват и плох подобный код на практике?

Себе дороже =)

LINUX-ORG-RU ★★★★★
()

Qt-шный стабильный ABI на pImpl-ах тебя бережет, но на такое использование его, афаик, не рассчитывали.

anonymous
()
Ответ на: комментарий от Deleted

Из второго следует, что это UB в случае если результат или аргументы такой С++ функции не являются POD-ами.

что-то я не уловил, как из второго это следует

Иначе говоря, в C++ для нет POD-типов может быть не такое ABI, как в C.

если тип не содержит 1) виртуальных функций, 2) шаблонов и 3) _множественного_ наследования, то он, по факту, ничем от POD не отличается

2 и 3 запрещено в Qt для всего, что является QObject

next_time ★★★★★
() автор топика
Ответ на: комментарий от I-Love-Microsoft

А как передать QString из библиотеки? По указателю? Для мелких данных оно не будет быстрее работать. Проблемы останутся те же. А если вынести функцию за пределы extern «C», то QLibrary не будет с этим работать.

next_time ★★★★★
() автор топика
Последнее исправление: next_time (всего исправлений: 2)
Ответ на: комментарий от I-Love-Microsoft

Загубили во мне великого писателя, хнык. За-гу-би-ли душеньку мою широкую компиляторы окаянные да сетевые игры безбожные, ато то мог же я же тексты писать великобуквенные, да на радость читающим труды мои, но зря всё барин! зря! Да писать мне до погибели теперь кратки слова да пустомысленные, бездушны! ээээххх аж душенька болить баа-рииин.

Ида не до погибели мне жить так, и да не до упокоя жить терзая душеньку не возделаю никому.

:D =) =))))

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

*ться

Писателем он хотем стать Уааахахахахаха (взоржало моё альтерэго)

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от next_time

Странно, возможно я чего-то не догоняю… А если добавить аргумент какого нить простого типа? Аля int.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

Чему ты удивляешься? Во втором комменте про манглинг написано.

anonymous
()
Ответ на: комментарий от anonymous

А именно

«C», which makes it possible to link with functions written in the C programming language, and to define, in a C++ program, functions that can be called from the modules written in C.

По стандарту оно даже компилироваться не обязано.

next_time ★★★★★
() автор топика

я в курсе, что оно вообще не должно работать

Почему? Разве extern «C» влияет на что-то кроме name mangling?

Linkage from C++ to objects defined in other languages

У тебя QString определен в C++, объектный файл произведен C++ компилятором.

kawaii_neko ★★★★
()
Ответ на: комментарий от kawaii_neko

Разве extern «C» влияет на что-то кроме name mangling?

по идее, не должен, мне как раз хотелось выяснить, может я чего не знаю и по какой-то причине, такое решение - плохое

кроме того, данный код будет выложен на гитхаб, и мне не хотелось бы, чтобы в подобную строчку кода меня потом тыкали

У тебя QString определен в C++, объектный файл произведен C++ компилятором.

совершенно верно, и тут важно что этот объектник скомпилирован внешними средствами и по отношению к библиотеке и по отношению к бинарю, иначе будет влиять Чем чреват и плох подобный код на практике? (комментарий) п.2

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

Во втором комментарии цитата из стандарта (черновики бесплатны, в стандарте как и в большинстве книг есть индекс).

Если суть в том, чтобы выключить манглинг для взаимодействия C++ кода с C++ кодом, то проблем быть не должно, так как C++ компилятор сам себя поймёт. Но стандарт такой способ использования не предусматривает, похоже.

xaizek ★★★★★
()

Таки в чём смысл? Как потом этот код используется? Вы манипулируете QString из C? Вот с этим проблемы могут легко возникнуть

caryoscelus
()
Ответ на: комментарий от next_time

стандарт - объёмный, да к тому же ещё и платный

Да к тому же его нельзя цитировать («no part of this publication may be reproduced or utilized...»). Но ты мог взять последний публичный драфт перед стандартом.

anonymous
()
Ответ на: комментарий от anonymous

ну так если вам cppreference не аргумент, то может и драфт стандарта не аргумент, кто ж вас знает

next_time ★★★★★
() автор топика
Ответ на: комментарий от anonymous

c©ISO/IECN3690— end example]7.4 Theasmdeclaration[dcl.asm]1Anasmdeclaration has the formasm-definition:asm (string-literal) ;Theasmdeclaration is conditionally-supported; its meaning is implementation-defined. [Note:Typicallyit is used to pass information through the implementation to an assembler.— end note]7.5 Linkage specifications[dcl.link]1All function types, function names with external linkage, and variable names with external linkage have alanguage linkage. [Note:Some of the properties associated with an entity with language linkage are specificto each implementation and are not described here. For example, a particular language linkage may beassociated with a particular form of representing names of objects and functions with external linkage, orwith a particular calling convention, etc.— end note] The default language linkage of all function types,function names, and variable names is C++language linkage. Two function types with different languagelinkages are distinct types even if they are otherwise identical.2Linkage (3.5) between C++and non-C++code fragments can be achieved using alinkage-specification:linkage-specification:externstring-literal{declaration-seqopt}externstring-literal declarationThestring-literalindicates the required language linkage. This International Standard specifies the se-mantics for thestring-literals"C"and"C++". Use of astring-literalother than"C"or"C++«is conditionally-supported, with implementation-defined semantics. [Note:Therefore, a linkage-specification with astring-literalthat is unknown to the implementation requires a diagnostic.— end note] [Note:It is recommendedthat the spelling of thestring-literalbe taken from the document defining that language. For example,Ada(notADA) andFortranorFORTRAN, depending on the vintage.— end note]3Every implementation shall provide for linkage to functions written in the C programming language,„C“,and linkage to C++functions,„C++“. [Example:complex sqrt(complex);// C++linkage by defaultextern „C“ {double sqrt(double);// C linkage}— end example]4Linkage specifications nest. When linkage specifications nest, the innermost one determines the languagelinkage. A linkage specification does not establish a scope. Alinkage-specificationshall occur only innamespace scope (3.3). In alinkage-specification, the specified language linkage applies to the functiontypes of all function declarators, function names with external linkage, and variable names with externallinkage declared within thelinkage-specification. [Example:extern „C“ void f1(void(*pf)(int));// the namef1and its function type have C language// linkage;pfis a pointer to a C functionextern „C“ typedef void FUNC();FUNC f2;// the namef2has C++language linkage and the// function’s type has C language linkageextern „C“ FUNC f3;// the name of functionf3and the function’s type// have C language linkagevoid (*pf2)(FUNC*);// the name of the variablepf2has C++linkage and// the type ofpf2is pointer to C++function that// takes one parameter of type pointer to C functionextern „C“ {static void f4();// the name of the function f4 has§ 7.5170 c©ISO/IECN3690// internal linkage (not C language// linkage) and the function’s type// has C language linkage.}extern „C“ void f5() {extern void f4();// OK: Name linkage (internal)// and function type linkage (C// language linkage) gotten from// previous declaration.}extern void f4();// OK: Name linkage (internal)// and function type linkage (C// language linkage) gotten from// previous declaration.void f6() {extern void f4();// OK: Name linkage (internal)// and function type linkage (C// language linkage) gotten from// previous declaration.}— end example] A C language linkage is ignored in determining the language linkage of the names of classmembers and the function type of class member functions. [Example:extern „C“ typedef void FUNC_c();class C {void mf1(FUNC_c*);// the name of the functionmf1and the member// function’s type have C++language linkage; the// parameter has type pointer to C functionFUNC_c mf2;// the name of the functionmf2and the member// function’s type have C++language linkagestatic FUNC_c* q;// the name of the data memberqhas C++language// linkage and the data member’s type is pointer to// C function};extern „C“ {class X {void mf();// the name of the functionmfand the member// function’s type have C++language linkagevoid mf2(void(*)());// the name of the functionmf2has C++language// linkage; the parameter has type pointer to// C function};}— end example]5If two declarations declare functions with the same name andparameter-type-list(8.3.5) to be members ofthe same namespace or declare objects with the same name to be members of the same namespace and thedeclarations give the names different language linkages, the program is ill-formed; no diagnostic is requiredif the declarations appear in different translation units. Except for functions with C++linkage, a functiondeclaration without a linkage specification shall not precede the first linkage specification for that function.§ 7.5171 c©ISO/IECN3690A function can be declared without a linkage specification after an explicit linkage specification has beenseen; the linkage explicitly specified in the earlier declaration is not affected by such a function declaration.6At most one function with a particular name can have C language linkage. Two declarations for a functionwith C language linkage with the same function name (ignoring the namespace names that qualify it) thatappear in different namespace scopes refer to the same function. Two declarations for a variable with Clanguage linkage with the same name (ignoring the namespace names that qualify it) that appear in differentnamespace scopes refer to the same variable. An entity with C language linkage shall not be declared withthe same name as an entity in global scope, unless both declarations denote the same entity; no diagnosticis required if the declarations appear in different translation units. A variable with C language linkage shallnot be declared with the same name as a function with C language linkage (ignoring the namespace namesthat qualify the respective names); no diagnostic is required if the declarations appear in different translationunits. [Note:Only one definition for an entity with a given name with C language linkage may appear inthe program (see 3.2); this implies that such an entity must not be defined in more than one namespacescope.— end note] [Example:int x;namespace A {extern „C“ int f();extern „C“ int g() { return 1; }extern „C“ int h();extern „C“ int x();// ill-formed: same name as global-space objectx}namespace B {extern „C“ int f();//A::fandB::frefer to the same functionextern „C“ int g() { return 1; }// ill-formed, the functiong// with C language linkage has two definitions}int A::f() { return 98; }//definition for the functionfwith C language linkageextern „C“ int h() { return 97; }// definition for the functionhwith C language linkage//A::hand::hrefer to the same function— end example]7A declaration directly contained in alinkage-specificationis treated as if it contains theexternspeci-fier (7.1.1) for the purpose of determining the linkage of the declared name and whether it is a definition.Such a declaration shall not specify a storage class. [Example:extern „C“ double f();static double f();// errorextern „C“ int i;// declarationextern „C“ {int i;// definition}extern „C“ static void g();// error— end example]8[Note:Because the language linkage is part of a function type, when indirecting through a pointer to Cfunction, the function to which the resulting lvalue refers is considered a C function.— end note]9Linkage from C++to objects defined in other languages and to objects defined in C++from other languagesis implementation-defined and language-dependent. Only where the object layout strategies of two language§ 7.5172 c©ISO/IECN3690implementations are similar enough can such linkage be achieved.

Ну, т.е. всё тоже самое, что на цппреференс, только чуть другими словами. Спрашивается, стоило туда лезть?

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

Ну, т.е. всё тоже самое, что на цппреференс, только чуть другими словами.

Мне так не кажется. Из этого намного сложнее сделать «вывод» что «вообще не должно компилироваться».

anonymous
()
Ответ на: комментарий от anonymous

Линковка к объектам других языков и наоборот на усмотрение разработчика компилятора. Т.е. разработчик имеет полное право решить, что раз классы, в т.ч. QString в С невозможны, и => код такой не может с С линковаться, то это ошибка.

next_time ★★★★★
() автор топика
Ответ на: комментарий от next_time

Вот именно, что разработчик может решить. А может не решить. Так что, откуда «компилироваться не должен по стандарту» взялось?

anonymous
()
Ответ на: комментарий от Thetan

Пижииба! Прагресс на лецо! Осталась ться тса подучить. :D

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от next_time

и мне не хотелось бы, чтобы в подобную строчку кода меня потом тыкали

Так не пиши дичь и не будут тыкать

Для мелких данных оно не будет быстрее работать.

Зато будет работать гарантированно

Да и вообще, зачем тебе этот говнокласс, верни const char* и не парься

annulen ★★★★★
()
Ответ на: комментарий от next_time

Ок. Я думал что «не должен компилировать» == «должен не компилировать».

anonymous
()

Короче,если очень приспичило явно эспортни и тупедефни функцию и всё, или для нужных функций делай обёртки где будет явное приведение типа. Проблема больше в том что подобная запись может поставить в тупик читающего, а не в самих данных, для С вообще всрать что там если всё явно описано и приведено к нужной размерности ИМХО. Делают же все обёртки и ты делай, а суть их часто не в необходимости технической, а человеческой что-бы понятно было. гы

LINUX-ORG-RU ★★★★★
()

Самые плохие выстрелы в ногу — те, которые не всегда стреляют. UB может отработать на одной системе и упасть на другой. И ещё очень хорошо, если оно упадёт в тестах CI или хотя бы у твоего коллеги до выпуска дистрибутива, а не у конечного пользователя.

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

А где тут UB? Тут вроде только implementation-defined.

next_time ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Годно, теперь всегда буду так читать.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.