Question

I'm trying to use protocol buffers in a simple C++ program. When I compile with g++ the program executes and exits normally. When I compile with clang++ the program fails, complaining that pointer being freed was not allocated.

Protocol Buffer Message Definition

package test;

message Test {
    required int32 id = 1;
    required string name = 2;
}

Main Class

#include <iostream>
#include "test.pb.h"

int main(void) {
    // Build the original message
    test::Test original;
    original.set_id(0);
    original.set_name("original");

    // Serialize the original message
    int size = original.ByteSize();
    char data[size];
    original.SerializeToArray(data, size);

    // Deserialize the data into a previously initialized message
    test::Test success;
    success.set_id(1);
    success.set_name("success");
    success.ParseFromArray(data, size);
    std::cout << success.id() << ": " << success.name() << std::endl;

    // Deserialize the data into an uninitialized message
    test::Test failure;
    failure.ParseFromArray(data, size); // FAILS HERE WITH CLANG++
    std::cout << failure.id() << ": " << failure.name() << std::endl;
}

g++ Output

theisenp$ g++ test.pb.cc main.cpp -lprotobuf -o g++.out
theisenp$ ./g++.out 
0: original
0: original

clang++ Output

theisenp$ clang++ test.pb.cc main.cpp -L/usr/local/lib -lprotobuf -stdlib=libstdc++ -o clang++.out
theisenp$ ./clang++.out 
0: original
clang++.out(9948,0x7fff71195310) malloc: *** error for object 0x7fff72ed6330: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

I'm new to both Protocol Buffers and Clang so it's entirely possible that I'm missing something obvious. Any ideas?

Edit

Some clarification on compiler versions. I'm running OSX Mavericks (10.9.1). By default, Mavericks maps calls to gcc and g++ to clang and clang++ respectively. I've installed gcc 4.8.2 independently and overridden the default behavior.

g++ Version

theisenp$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc48/4.8.2/libexec/gcc/x86_64-apple-darwin13.0.2/4.8.2/lto-wrapper
Target: x86_64-apple-darwin13.0.2
Configured with: ../configure
    --build=x86_64-apple-darwin13.0.2
    --prefix=/usr/local/Cellar/gcc48/4.8.2
    --enable-languages=c,c++,objc,obj-c++
    --program-suffix=-4.8
    --with-gmp=/usr/local/opt/gmp4
    --with-mpfr=/usr/local/opt/mpfr2
    --with-mpc=/usr/local/opt/libmpc08
    --with-cloog=/usr/local/opt/cloog018
    --with-isl=/usr/local/opt/isl011
    --with-system-zlib
    --enable-version-specific-runtime-libs
    --enable-libstdcxx-time=yes
    --enable-stage1-checking
    --enable-checking=release
    --enable-lto
    --disable-werror
    --enable-plugin
    --disable-nls
    --disable-multilib
Thread model: posix
gcc version 4.8.2 (GCC) 

clang++ Version

theisenp$ clang++ -v
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.2
Thread model: posix
Was it helpful?

Solution

As discussed in comments, it's important that libprotobuf is compiled with the same stdlib that you use when compiling your code, since libprotobuf uses STL types (especially std::string) in its interface. If you've installed GCC 4.8, it will use GCC's libstdc++ 4.8. The Clang shipped with Xcode, meanwhile, will use whatever stdlibs ship with Xcode, so even if you tell it --stdlib=libstdc++, it may be an incompatible version.

OTHER TIPS

I suspect your problem may be here:

int size = original.ByteSize();
char data[size];

Variable length arrays are not valid C++ (they are permitted in C99), they are a GCC extension.

I'd suggest using a dynamically allocated buffer and see if the problem persists. There is some discussion about clang and VLAs circa 2010 here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top