Read Ctxt from stream in using HElib

Assume you need to read Ctxt from a stream (file, socket, or whatever) in using HElib, the general pattern is like this:

Ctxt ctxt(*pubKey);
while (fs >> ctxt)
{
    std::cout << ++count << std::endl;
}

But this will trigger following error (If you use one version of HElib to encrypt Ctxt, while use another version of HElib to process Ctxt, this error may occur too.):

Searching for cc='[' (ascii 91), found c='▒' (ascii -1)

The root cause of this issue is about handling EOF. To solve this issue, there are 2 methods:

(1)

Ctxt ctxt(*pubKey);
while (!fs.eof())
{
    fs >> ctxt >> std::ws;
    if (fs.fail())
    {
        break;
    }
}

fs >> ctxt >> std::ws; will stop when the EOF is met. Since fs.fail() won’t return true when eofbit is set (please refer here), fs.eof() will becometrue to terminate while-loop.

(2) know how many Ctxt will be read in advance. For example:

Ctxt ctxt(*pubKey);
for (int i = 0; i < 10; i++)
{
    fs >> ctxt;
}

Be careful of file sequence in linking process

Check following A.h:

# cat A.h
#pragma once

#include <iostream>
#include <vector>

class A
{
public:
        std::vector<int> v;
        A()
        {
                v.push_back(1);
                std::cout << "Enter A's constructor...\n";
        }
        int getFirstElem()
        {
                v.push_back(2);
                std::cout << "Enter A's getFirstElem...\n";
                return v[0];
        }
        ~A()
        {
                std::cout << "Enter A's destructor...\n";
        }
};

int func();

And A.cpp:

# cat A.cpp
#include "A.h"

static A a;

int func()
{
        return a.getFirstElem();
}

The A.cpp just define a A‘s static instance, and a func() returns first element in a‘s internal vector.

Check another file which utilizes A.h and A.cpp:

# cat hello.cpp
#include <iostream>
#include "A.h"

static int gP = func();

int main()
{
    std::cout << gP << std::endl;
    return 0;
}

Compile them:

# clang++ -c hello.cpp
# clang++ -c A.cpp

Link hello.o first and execute the program:

# clang++ hello.o A.o
# ./a.out
Enter A's getFirstElem...
Enter A's constructor...
2
Enter A's destructor...

Then link A.o first and execute the program:

# clang++ A.o hello.o
# ./a.out
Enter A's constructor...
Enter A's getFirstElem...
1
Enter A's destructor...

The results are different. In first case, when call a‘s getFirstElem() function, its constructor is not even called. Please pay attention to it!

Out-of-bound access of vector in C++

Today I debugged a crash bug of C++ program, and the core dump is like this:

Program terminated with signal SIGABRT, Aborted.
#0  0x00007f57ba2ed860 in raise () from /usr/lib/libc.so.6
(gdb) bt
#0  0x00007f57ba2ed860 in raise () from /usr/lib/libc.so.6
#1  0x00007f57ba2eeec9 in abort () from /usr/lib/libc.so.6
#2  0x00007f57ba330437 in __libc_message () from /usr/lib/libc.so.6
#3  0x00007f57ba336d34 in malloc_printerr () from /usr/lib/libc.so.6
#4  0x00005593dc2f7b6c in __gnu_cxx::new_allocator<int>::deallocate (this=0x7ffc65848820, __p=0x5593dce6fac0)
    at /usr/include/c++/7.2.1/ext/new_allocator.h:125
#5  0x00005593dc2f7a36 in std::allocator_traits<std::allocator<int> >::deallocate (__a=..., __p=0x5593dce6fac0, __n=12)
    at /usr/include/c++/7.2.1/bits/alloc_traits.h:462
#6  0x00005593dc2f789a in std::_Vector_base<int, std::allocator<int> >::_M_deallocate (this=0x7ffc65848820,
    __p=0x5593dce6fac0, __n=12) at /usr/include/c++/7.2.1/bits/stl_vector.h:180
#7  0x00005593dc2f7543 in std::_Vector_base<int, std::allocator<int> >::~_Vector_base (this=0x7ffc65848820,
    __in_chrg=<optimized out>) at /usr/include/c++/7.2.1/bits/stl_vector.h:162
#8  0x00005593dc2f71cf in std::vector<int, std::allocator<int> >::~vector (this=0x7ffc65848820,
    __in_chrg=<optimized out>) at /usr/include/c++/7.2.1/bits/stl_vector.h:435
......

From the stack trace, we can see the abort() occurred in vector‘s destructor function. After some debugging, I find the root cause is the general “out-of-bound” error, which accessed the memory beyond the vector space. But the caveat is that “out-of-bound” error may be silent and give you no hurt apparently. E.g., I write a simple test program:

#include <vector>

void fun() {
    std::vector<int> v(1);

    auto it = v.begin();
    for (int i = 0; i < 100; i++) {
        *it++ = i;
    }
}
int main() {
    fun();
    return 0;
}

Build and run it:

# g++ -g test.cpp
# ./a.out
# ./a.out

The application goes well. So we really should pay enough attention to vector access.

Test of freeing 2-dimension vector memory in C++

C++ Vector Memory Release introduces how to release vector memory in C++, but the example only involves 1-dimension vector. I write a small application to verify freeing 2-dimension vector (the OS is OpenBSD) :

#include <unistd.h>
#include <vector>
#include <iostream>

using namespace std;

int main(void) {
    vector<vector<char>> vec(1024 * 1024, vector<char>(1024));

    cout << "Before freeing memory, sleep 30 seconds ..." << endl;
    sleep(30);
    vector<vector<char>>().swap(vec);

    cout << "Sleep now ..." << endl;
    sleep(300);
    return 0;
}

Use clang++ to build and run it:

# clang++ -std=c++11 free.cpp
# ./a.out

(1) When “Before freeing memory, sleep 30 seconds ...” is printed, checked the memory usage of program:

1

We can see the program occupied more than 1G memory.

(2) After “Sleep now ...” is outputted, the memory usage began to descend, and when it became stable, the memory program consumed is only about 19K:

2

P.S., the full code is here.

Be careful of FHEcontext’s shallow copy feature in HElib

Check following code which uses HElib:

class A
{
    FHEcontext context;
public:
    FHEcontext& getContext()
    {
        return context;
    }
};

void func()
{
    auto context = a.getContext();
    ......
}

A a;

int main(void)
{
    ......
    func();
    ......
    return 0;
}

In func():

......
auto context = a.getContext();
......

It will allocate a local variable context whose type is FHEcontext, not “FHEcontext&“, and the point is it will be shallow copy of FHEcontext:

class FHEcontext {

......
  //! @breif A default EncryptedArray
  const EncryptedArray* ea;
......
}

FHEcontext::~FHEcontext()
{
  delete ea;
}

So when the local variable context is destroyed, the memory of ea is also released; this will lead to context member of class A references a already freed memory. That will be a disaster!

References:
auto specifier type deduction for references;
The issue about FHEcontext’s copy constructor/assignment operator.