将 const char* 传递给构造函数会给出 null

Posted

技术标签:

【中文标题】将 const char* 传递给构造函数会给出 null【英文标题】:Passing const char* into constructor gives null 【发布时间】:2017-12-10 17:03:38 【问题描述】:

我正在尝试制作一个简单的记录器来记录到一个文件,以便为我提供有关我的程序的调试信息。我想避免使用图书馆,所以我自己做一个。

日志记录.cpp

#include <string.h> // String stuff
#include <time.h>   // Time

#include "logging.hpp"

// Cathooks main logging util
CatLogger g_CatLogging("/tmp/nekohook.log");
//CatLogger g_CatLogging;

CatLogger::CatLogger(const char* _file_path, bool _ptime) : ptime(_ptime) 
     file_path = _file_path;

CatLogger::~CatLogger()    fclose(log_handle); 

void CatLogger::log(const char* fmt, ...) 

    // Basicly an init, because this cant be done on construct
    if (log_handle == nullptr) 
        log_handle = fopen(file_path, "w");
    

    // Print our time if needed
    if (ptime) 
        // Get our time
        time_t current_time = time(0);
        struct tm* time_info = localtime(&current_time);

        // print it to a string
        char timeString[10];
        strftime(timeString, sizeof(timeString), "%H:%M:%S", time_info);

        // Print the time into the log
        fprintf(log_handle, "%% [%s] ", timeString);
    

    // Get the string we want to log
    char buffer[1024];
    va_list list;
    va_start(list, fmt);
    vsprintf(buffer, fmt, list);
    va_end(list);

    // Write our log to the file
    fprintf(log_handle, "%s\n", file_path, buffer);
    fflush(log_handle);

    // Push result var to a console here, if i ever make a console api

日志记录.hpp

#include <stdarg.h> // ... arg
#include <stdio.h> // fopen(), fprint(), fputs()

class CatLogger 
public:
  CatLogger(const char* _file_path, bool _ptime = false);
  ~CatLogger();
  void log(const char* fmt, ...); // Use to log with
private:
  FILE* log_handle = 0; // Handle used to log to files with
  const char* file_path; // Path to log file
  const bool ptime; // Whether to print time
;

// Use this to log
extern CatLogger g_CatLogging;

当我使用日志功能时,它失败了。我不知道为什么。我制作了一个虚拟函数,该函数在运行以从输入的 gdb 获取信息时崩溃。我将file_path 变量输入其中,它返回0x0。我不确定为什么会发生这种情况,我已经将一个示例可执行文件与我正在使用的库分开,并且它可以完美运行。这可能是由于我链接库的方式还是缺少链接?

这是我正在使用的库,其中包含一个直接指向日志文件的链接。 https://github.com/oneechanhax/nekohook/blob/master/src/util/logging.cpp

由于 fopen 没有返回文件句柄,它在 fprintf() 上都崩溃了,这反过来又是因为 const char* 由于某种原因没有被传递。

请告诉我调试此问题的方法或指出问题出在哪里,因为我正在为自己尝试而不知所措。

编辑: 如果我在CatLogger::log中替换以下内容

if (log_handle == nullptr) 
    log_handle = fopen(file_path, "w");

如下

if (log_handle == nullptr) 
    log_handle = fopen("/tmp/nekohook.log", "w");

它现在可以工作,但我现在无法更改其他日志类的日志位置...

编辑2: 这是一些调试信息。不知何故, const char* 没有保存到类中。这就是我的主要问题......

example

可能字符串在构造后变成了null……

【问题讨论】:

听起来像是一个可能的静态初始化命令失败,如果fopen 实现有自己的静态数据,它需要初始化才能工作。你的报告听起来像是因为这样的事情而失败了。 建议。如果您使用的是 C++,请使用 C++ 头文件而不是 C 头文件。 #include &lt;cstring&gt;#include &lt;ctime&gt;#include &lt;cstdarg&gt;。' 很可能你的 g_CatLogging 全局在被调用时还没有被初始化。您是否尝试在调用 main 之前进行日志记录? 对 CatLogger 类使用单例设计模式:***.com/questions/1008019/… 要查看发生了什么,请将许多跟踪 cmets 添加到 std::cout 或更好地添加到 std::cerr。 【参考方案1】:

有很多潜在的错误。

if (log_handle == nullptr) 
    log_handle = fopen(file_path, "w");
    if(!log_handle) 
        perror("File opening failed"); // check your console output.
        return EXIT_FAILURE;
    



// Get the string we want to log
char buffer[1024];
va_list list;
va_start(list, fmt);
vsprintf(buffer, fmt, list); // potential segmentation fault
va_end(list);

改用这个

int vsnprintf( char* buffer, std::size_t buf_size, const char* format, va_list vlist ); //  (since C++11)

而且程序是多线程的。

【讨论】:

【参考方案2】:

这是静态初始化顺序失败的情况,其中 const char* 在调用函数之前不会被初始化。 解决方案是首先将文件链接与其他文件进行比较,然后对象现在可以工作。

【讨论】:

以上是关于将 const char* 传递给构造函数会给出 null的主要内容,如果未能解决你的问题,请参考以下文章

我可以将 const char* 数组传递给 execv 吗?

以这种格式将 argv 变量传递给 main 的结果 main( int argc, char const * argv )

如何将变量传递给 const char 类型?

拷贝构造函数

C++ 将 char 转换为 const char*

为啥在通过 const 引用传递临时值时调用复制构造函数?