Istvan
Istvan

Reputation: 1665

Trigger a compiler error when trying to add char* to int?

C++ compilers happily compiles this code, with no warning:

int ival = 8;
const char *strval = "x";
const char *badresult = ival + strval;

Here we add a char* pointer value (strval) to an int value (ival) and store the result in a char* pointer (badresult). Of course, the content of the badresult will be total garbage and the app might crash on this line or later when it is trying to use the badresult elsewhere. The problem is that it is very easy to make such mistakes in real life. The one I caught in my code looked like this:

message += port + "\n";

(where message is a string type handling the result with its operator += function; port is an int and \n is obviously a const char pointer).

Is there any way to disable this kind of behavior and trigger an error at compile time?

I don't see any normal use case for adding char* to int and I would like a solution to prevent this kind of mistakes in my large code base. When using classes, we can create private operators and use the explicit keyword to disable unneeded conversions/casts, however now we are talking about basic types (char* and int).

One solutions is to use clang as that has a flag to enable warning for this. However I can't use clang, so I am seeking for a solution that triggers a compiler error (some kind of operator overload or mangling with some defines to prevent such constructs or any other idea).

Upvotes: 1

Views: 711

Answers (3)

Is there any way to disable this kind of behavior and trigger an error at compile time?

Not in general, because your code is very similar to the following, legitimate, code:

 int ival = 3;
 const char *strval = "abcd";
 const char *goodresult = ival + strval;

Here goodresult is pointing to the last letter d of strval.

BTW, on Linux, getpid(2) is known to return a positive integer. So you could imagine:

 int ival = (getpid()>=0)?3:1000;
 const char *strval = "abcd";
 const char *goodresult = ival + strval;

which is morally the same as the previous example (so we humans know that ival is always 3). But teaching the compiler that getpid() does not return a negative value is tricky in practice (the return type pid_t of getpid is some signed integer, and has to be signed to be usable by fork(2), which could give -1). And you could imagine more weird examples!

You want compile-time detection of buffer overflow (or more generally of undefined behavior), and in general that is equivalent to the halting problem (it is an unsolvable problem). So it is impossible in general.

Of course, one could claim that a clever compiler could warn for your particular case, but then there is a concern about what cases should be useful to warn.

You might try some static source program analysis tools, perhaps Clang static analyzer or Frama-C (with its recent Frama-C++ variant) - or some costly proprietary tools like Coverity and many others. These tools don't detect all errors statically and takes much more time to execute than an optimizing compiler.

You could (for example) write your own GCC plugin to detect such mistakes (that means developing your own static source code analyzer). You'll spend months in writing it. Are you sure it is worth the effort?

However I can't use clang,

Why? You could ask permission to use the clang static analyzer (or some other one), during development (not for production). If your manager refuses that, it becomes a management problem, not a technical one.


I don't see any normal use case for adding char* to int

You need more imagination. Think of something like

puts("non-empty" + (isempty(x)?4:0));

Ok that is not very readable code, but it is legitimate. In the previous century, when memory was costly, some people used to code that way.

Today you'll code perhaps

if (isempty(x))
    puts("empty");
else
    puts("non-empty")

and the cute thing is that a clever compiler could probably optimize the later into the equivalent of former (according to the as-if rule).

Upvotes: 1

user743382
user743382

Reputation:

In the first example in your question, really, compilers should issue a warning. Compilers can trivially see that the addition resolves to 8 + "x" and clang does indeed optimise it to a constant. I see the fact it doesn't warn about this as a compiler bug. Although compilers are not required to warn about this, clang goes through great efforts to provide useful diagnostics, and it would be an improvement to diagnose this as well.

In the second example, as Matteo Italia pointed out, clang does already provide a warning option for this, enabled by default: -Wstring-plus-int. You can turn specific warnings into errors by using -Werror=<warning-option>, so in this case -Werror=string-plus-int.

Upvotes: 1

shawn
shawn

Reputation: 4363

No way. It is valid syntax, and very useful in many cases.

Just think about you were to write int b=a+10 but you wrote int b=a+00 incorrectly, the compiler won't know it is an error by mistake.

However, you can consider to use C++ classes. Most C++ classes are well designed to prevent such obvious mistakes.

Upvotes: 1

Related Questions