-2

C++ newbie and have been writing a C++ program, but it finally breaks at the point of calling a lib function call from ctime.

The error shows info like this:
malloc(): memory corruption

AFAIK, this error(memory corruption) should be resulted from operate on out-of-bound memory address. And the print format represents YYYY-MM-DD-HH-MM, which is listed here, shows that the length should be definitively less than 100.

Additional info:
- The program is compiled with flags: "-O3 -g -Wall -Wextra -Werror -std=c++17"
- Compiler: g++ 7.4.0
- System: WSL Ubuntu-18

NOTE: This Code DOES NOT compiles and is NOT REPRODUCIBLE for the problem, See updates below

/** class file **/
#include <sys/wait.h>
#include <sys/types.h>  
#include <unistd.h>
#include <errno.h>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <ios>
#include <fcntl.h>
#include <algorithm>
#include <cctype>
#include <ctime>
#include <limits>
#include "cache-proxy.hpp"

static int PROXY_CONFIG = 0;

void get_timestamp(char *buffer, int len);
std::string get_cwd(void);

CacheProxy::CacheProxy(__attribute__((unused)) const std::string& node)
{ 
    curr_dir = fs::get_cwd();
    Logger::get().info("curr_dir " + curr_dir);
    proxy_path = "/usr/sbin/squid";
    std::string squid("squid");

    char buff[200];
    get_timestamp(buff, 200);    // error pops
    std::string proxy_config_path;

    /** plenty of codes following, but commented**/
}

void ~CacheProxy(){}

void get_timestamp(char *buffer, int len)
{
    time_t raw_time;
    struct tm *time_info;
    time(&raw_time);
    time_info = std::localtime(&raw_time);
    std::strftime(buffer, len, "%F-%H-%M", time_info);
    return;
}

// originally from other files, for convenient to be moved into this file 
std::string get_cwd(void)
{
    char path[PATH_MAX];
    std::string retval;
    if (getcwd(path, sizeof(path)) != NULL) {
        retval = std::string(path);
    } else {
        Logger::get().err("current_path", errno);
    }
    return retval;
}


/** header file **/ 
#pragma once
#include <string>

class CacheProxy:
{
private:
    int server_pid;
    std::string proxy_path;
    std::string curr_dir;
    std::string squid_pid_path;
    ;

public:
    CacheProxy(const std::string&);
    ~CacheProxy() override;

};

/** main file **/
int main(){
    Node node(); // the parameter is never used in the CacheProxy constructor though
    CacheProxy proxy(node); // error pops
    proxy.init();
}

Thanks for any advices or thoughts.


Updates:
code updated as above and there are three major files. The code shows the exact same sequences of the logic of my original codebase by leaving out irrelevant codes(I commented them out when run into the errors), but please forgive me in giving out such rough codes.

Basically the the error pops during the object initialization and I currently assume that problems be either in get_cwd or localtime.

Please indicate if you need more infomations, though I think other codes are non-relevant indeed.


Updates Dec 21:
After commenting out different parts of the original code, I managed to locate the error part but cannot fix the bug. Opinions from comments are indeed true that the memory corruption error should originated from somewhere beforehand, however, what I am going to do to fix this problem, is somewhat different from other answers since I use setcap for my program and cannot use valgrind in this scenarios.

I used another tool called ASan(Address Sanitizer) to do the memory check. It was really easy to find out where the memory corruption is originated from with the tool and it has comprehensive analysis when the error occurs at runtime. I added support in the compiler and found out the main problem in my case is the memory allocation for string variables in CacheProxy class.

So far, it has turned out to be another problem which is "why there are indirect memory leakages originated from allocating memory for string objects when constructor of this class is called", which I will not collapsed here in this question.

But it is really a good lesson for me that Memory problems actually have various types and causes, you cannot stare onto the source code for solving a problem which is not "index out of bound" or "illegal address access"(segfault) problem. Many tools are really handy and specialized in dealing with these things, so go and grab your tools.

leonyuuu
  • 11
  • 7
  • https://stackoverflow.com/questions/39507994/malloc-seg-fault-in-localtime – Zhang Dec 19 '19 at 06:26
  • 2
    With the obvious issues fixed, the code [compiles and runs](https://onlinegdb.com/S1OWd5dAH) without issue for me. – David Schwartz Dec 19 '19 at 06:26
  • 1
    The problem is probably in other code that you left out of the question. – Barmar Dec 19 '19 at 06:27
  • @Zhang I tried moments ago, but my program run with setcap and it is not allowed to be executed by the valgrind. Is there anyway around? – leonyuuu Dec 19 '19 at 06:50
  • @DavidSchwartz thanks for fast response. I didn't mention that this is only a part of my code, and I was trying to commented other codes out and happened to find that this line of code was always giving out the error code. Definitely I ran this piece of code(with all needed headers definitely ;-) in a separate executable. My question is that since the variable is not obtained from previous result(the buff), why does the error happen when I only leave this line of code in the file and the error won't happen when I removed these lines. – leonyuuu Dec 19 '19 at 07:00
  • 1
    Please show code that you actual tested *as is* and in the form of a [repro]. The shown code does not compile and it is not productive to speculate about what you actually ran. – walnut Dec 19 '19 at 07:01
  • @Barmar see above – leonyuuu Dec 19 '19 at 07:01
  • 1
    @leonyuuu You won't really know that until you find the error, and the error almost certainly isn't in this code. Either use a tool like valgrind to find the error or iterate removing code and seeing if you still have the error until you find the smallest code that reproduces the error. – David Schwartz Dec 19 '19 at 07:20
  • @walnut the original code is relatively complex and I think most of them are well tested other than this file and its header. The error basically starts with the initialization of one object of this class – leonyuuu Dec 19 '19 at 07:41
  • @leonyuuu Your code does still not compile and after fixing all of the issues with it, it still runs fine without error, see https://godbolt.org/z/JzCAEc. The problem is that we cannot help you if we don't see the code producing the problem. – walnut Dec 19 '19 at 07:54
  • Make a copy of your program code and start removing components that you think are unrelated to the issue one-by-one, each time testing whether the problem occurs, until there is nothing left to remove without the error vanishing. Then you will have a [repro] that we can talk about and in most cases this process itself will make the mistake obvious. Also run your program with the address sanitizer or valgrind and look at what they tell you where the issue. – walnut Dec 19 '19 at 07:58
  • `Node node();` is a function declaration – M.M Dec 19 '19 at 08:03
  • `CacheProxy proxy(node);` cannot possibly compile as the only constructor of `CacheProxy` takes `std::string&` argument. Unless, of course, this is not the real code – M.M Dec 19 '19 at 08:04
  • `class CacheProxy: {` is a syntax error also – M.M Dec 19 '19 at 08:05
  • @M.M There are too many syntax issues to list. I went through and fixed them all in the godbolt I linked. – walnut Dec 19 '19 at 08:06
  • @leonyuuu Also check the return values of all the library calls. `std::time`, `std::localtime`, etc. all can fail. See their references on e.g. [cppreference.com](https://en.cppreference.com/w/). – walnut Dec 19 '19 at 08:08
  • @walnut Sorry for not providing the comprehensive codebase, and appreciate your effort in trying to compile this incomplete code since I removed parts of the original ones and renamed some of the variables. I will try to make a reproducible example later – leonyuuu Dec 19 '19 at 16:15
  • @M.M thanks for your help, I misunderstood the regulation of the community and were just seeking for answers without providing a reproducible code – leonyuuu Dec 19 '19 at 16:16

2 Answers2

1

Any crash inside malloc or free is probably cause of a earlier heap corruption.

Your memory is probably corrupted earlier.

If you're using Linux, try running your program under valgrind. Valgrind can help you find out this kind of error.

Zig Razor
  • 3,381
  • 2
  • 15
  • 35
0

The 'obvious fixes' refered to by David is:

#include <iostream>
#include <ctime>
#include <cstdio>

void get_timestamp(char *buffer, int len)
{
time_t raw_time;
struct tm *time_info;
time(&raw_time);
time_info = localtime(&raw_time);                // the line of code that breaks
strftime(buffer, len, "%F-%H-%M", time_info);
return;
}

int main() {
char buff[100];
get_timestamp(buff, 100);
std::cout << std::string(buff);
return 0;
}
slashmais
  • 7,069
  • 9
  • 54
  • 80