Hiding functions in C/C++

There is a project of many files. Some functions from some modules are called from other modules, so those functions must have a global scope. However, those functions are part of a system and they have many side effects. So those functions should be called only from the right places and at the right times.

What would be the elegant way to ensure that idiots won't call the system functions just because the functions are visible?

In C++, I can hide those functions into classes or namespaces, so the functions will be accessible only where it is needed. Is there a way to do something like that in C ?

Vladimir Vassilevsky DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky
Loading thread data ...

No - AFAIK in C, it's all or nothing. The only way to avoid the functions being easily callable is to omit their declarations from the header files, or to "hide" them in extra header files. Nothing can stop users declaring them with explicit "extern" statements and calling them, however.

One possible way to neaten things would be to have your module header like this:

#ifndef __module_h__ #define __module_h__

#ifdef AllowSystemCalls #define SYSCALL #else // gcc has a nice __attribute__ syntax to use here // warning attribute is another option #define SYSCALL __attribute__((error("I can't let you do that, Dave"))) #endif

extern void NormalFunction(void); extern void SYSCALL SystemFunction(void);

Reply to
David Brown

Yes -- until I saw "elegant," above. Is a cfront style solution off the table?

Jon

P.S. Here's my 'dump out' which is probably NOT elegant.

You linker may support features the c compiler doesn't directly provide, but where you can write a program to modify the object file to gain access. c tends to only require basic linker features, though, and the linker may not have any support for something useful.

Circa 1980, c++ used to be called "c with classes" and targeted c, just fine. If cfront were available (I don't know that it is, or isn't, now), it might be able to act as a kind of pre-processor of sorts for c code that used just the class-syntax as an extension to get close. You'd just write "mostly c" and use the class method and let cfront mangle stuff for you and produce usable c -- except for the mangling which you may or may not feel strongly about.

If you are fine with name mangling but no cfront is handy, you could consider writing something short and sweet to get the job done as a preprocessing step.

Otherwise, if you feel strongly about only using a simple editor and c and nothing else and not interested in finding out about or using any special linker features, bypassing what the c compiler does by modifying object files before the linker step, then you are stuck with the module-local scope or the global-at-link-time scope for which c provides syntax and can do what generations have done before you -- write unique names and otherwise don't include extern statements for them in modules that shouldn't be using them. That won't control anyone else who links, though.

I suppose you could consider something, not unlike a librarian of some kind, that allows you to prelink some object modules together and then strip out certain global names afterwards that you don't want publicized and supply that as a linkage unit to others. It would block them even if they tried to declare the names, then. Again, might be custom work. But there it is.

Reply to
Jon Kirwan

What about the "static" keyword? Sure, it'll only let you call the function in the file in which you defined the static function, but it'll be marked as private in the object file and you shouldn't be able to link against it extern tricks or no. If you want to share the static function across several files, you're generally out of luck.

Besides, just document the library's real api, and say if you deviate from it there is no guarantee of correct behavior and you won't support them.

C++ with namespaces or private member functions don't fix anything for a determined hacker. I could, outside of any legal C++ means, call private methods in a class I don't have a header file to if I wanted to and only a pointer to it.

Here is an example:

#include #include

class Foo { public: Foo() {}; ~Foo() {}; void callit(int c) { hello(c); }

private: void hello(int x) { printf("Hello: %d\n", x); } };

/* gcc 4.1.2 C++ ABI C linkage call */ extern "C" { void _ZN3Foo5helloEi(void*, int); }

int main(int argc, char *argv[]) { Foo f;

/* normal way */ f.callit(10);

/* naive method to break the 'private' protection. */ _ZN3Foo5helloEi(&f, 20);

return 0; }

If I cared more, I could probably deduce what the function table looks like from the object and do some void (**func)(void*, int) hackery to figure out a callable function form the class pointer.

So, in reality, you should be asking: What is my threat model?

If it is simply "To prevent idle stupidity", then document the API only, and don't support it if they do anything else. If it is "ensure noone can ever call into code I don't want them to" you're screwed--it is always possible.

Later,

-pete

Reply to
Peter Keller

I got the impression from the O/P that the functions had to have external linkage because they could be called from other modules, but that he wanted to make it hard to call them. If "static" was the answer, then I think Vladimir would have figured that out himself.

It's always possible to work around any technical restrictions that are put in. And clear documentation is also always important. But I think the aim here is to make it hard to break the API rules - it limits the risk of accidents by people who don't read the documentation properly, or who think they know better than the document writer.

Reply to
David Brown

You mean beyond the usual C dodge of putting all the 'real' functionality in static functions that live behind firewall functions?

In my experience, the only way to keep the idiots from doing stupid things with your code is to keep the idiots away from your code, or your code away from the idiots.

At some point I think you just have to accept that you do a good job documenting the functions you want used, you either don't mention the other ones or you post warnings, then you make sure that if someone screws up with your code you get paid by the hour to fix it.

I believe that the Gnu linker can link .o files into .o files, and to remove functions from the public list. I've never done it, so you'll have to do your own manual reading. Put these together (if they work) and you have a mechanism for linking up packages of functionality into a .o file that only offers linkage for "approved" functions.

--

Tim Wescott
Wescott Design Services
http://www.wescottdesign.com

Do you need to implement control loops in software?
"Applied Control Theory for Embedded Systems" was written for you.
See details at http://www.wescottdesign.com/actfes/actfes.html
Reply to
Tim Wescott

That will require some unusual manual work, which will hopefully give them a clue that the things are not supposed to be done in that way.

Thank you, David. That works!

VLV

Reply to
Vladimir Vassilevsky

Ah, here we go again, wanting to have the cake and eat it, too.

Well, no: a given code module has _no_ control over timing or place of calls outside its own source and header file. Thus there clearly can be no way for it to test for what the "right" place might look like, or when or not is the right time.

In short: if there are functions that shouldn't be called from the outside unless some conditions are met, you must check those conditions _inside_ those functions.

There's no such thing as an idiot-proof tool. Nature is just way too good at designing idiots for such an effort to succeed.

No. Those methods offer no protection against the kind of inopportune calls you described. Anyone can call a function thus "hidden" via the namespace or class it's declared in just as easily as they can call a default-namespace, global function. There's no condition whatsoever about when or from where they can issue such a call.

Reply to
Hans-Bernhard Bröker

Not elegant - based on discipline

use separate header files:

API level functions to be used by all - moduleName.h

low-level functions to be used only by the "experts" - moduleNameP.h

- P for private functions and private types that can't be static

enforce by peer review or some kind of checker script

Reply to
Marco

Isn't that true of *all* code? :>

Make them *in*-visible. If you *really* want to keep folks from invoking them, then put a gatekeeper as your interface for the outside world *to* your code. This is similar to "trapping" to a privileged layer.

You've not indicated what your platform is so all bets are off as to what a developer *can* do (e.g., if he can force the PC to take on any *value*, then he can access any *thing*).

I like funneling accesses to my code through a narrow interface. Think of it as the published API for a client-server interface -- even if the "client" is colocated with the "server".

This also is a boon to debugging as you can interpose a simple debug/diagnostic/logging layer that tracks invocations (logging arguments, results, timestamps, ... whatever). That "feature" can make wanting to use this published interface far more attractive than trying to use "undocumented features".

You just create an API (documented with an appropriate header file for whatever language binding you choose) and then "strip" the rest of the executable.

C++ doesn't give you any better "protection"/hiding. It just helps keep honest (and intelligent!) people honest.

Reply to
D Yuniskis

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.