C++CGI脚本,读取表单数据

C++ CGI script, reading form data

本文关键字:表单 数据 读取 脚本 C++CGI      更新时间:2023-10-16

我一直在使用本教程来制作C++CGI脚本。但是,当我尝试读取表单 POST 数据时,它没有编译:

  char* lpszContentLength = getenv("CONTENT_LENGTH");
  char* lpszBuffer;
  int nContentLength = atoi(lpszContentLength);
  lpszBuffer = malloc(lpszContentLength+1);  // allocate a buffer
  memset(lpszBuffer, 0, lpszContentLength+1);  // zero it out
  fread(lpszBuffer,1,lpszContentLength,stdin);  // get data

这是编译器的抱怨:

cgi.cpp: In function ‘int main()’:
cgi.cpp:12: error: invalid conversion from ‘char*’ to ‘size_t’
cgi.cpp:12: error:   initializing argument 1 of ‘void* malloc(size_t)’
cgi.cpp:12: error: invalid conversion from ‘void*’ to ‘char*’
cgi.cpp:13: error: ‘memset’ was not declared in this scope
cgi.cpp:15: error: invalid conversion from ‘char*’ to ‘size_t’
cgi.cpp:15: error:   initializing argument 3 of ‘size_t fread(void*, size_t, size_t, FILE*)’

其中 ln 12 是以 "lpszBuffer" 开头的那个。

我是C++新手,所以我不确定如何解决这个问题,或者为什么会发生这种情况。也许它只是过时的代码...我很乐意接受其他一些解决方案来从 POST 请求中读取数据。

编辑:我已经根据你们的修复程序更新了代码。

  char* lpszContentLength = getenv("CONTENT_LENGTH");
  char* lpszBuffer;
  int nContentLength = atoi(lpszContentLength);
  lpszBuffer = (char*)malloc(nContentLength+1);  // allocate a buffer
  memset(lpszBuffer, 0, nContentLength+1);  // zero it out
  fread(lpszBuffer,1,nContentLength,stdin);  // get data

但是,我仍然从atoi得到一个分段错误:

==23419== Invalid read of size 1
==23419==    at 0x498DA8C: ____strtol_l_internal (strtol_l.c:298)
==23419==    by 0x498D7EF: strtol (strtol.c:110)
==23419==    by 0x498AB60: atoi (atoi.c:28)
==23419==    by 0x8048899: main (in .../cgi.cpp.cgi)
==23419==  Address 0x0 is not stack'd, malloc'd or (recently) free'd

这里有什么问题?我假设如果 POST 为空白,它与 POST 表单提交有关......

这是 C++ 的类型转换问题。 lpszBuffer是一个char*,但是,malloc返回一个void*。所以你需要把它投射到char*.另请注意,您正在尝试使用char*(lpszContentLength)作为整数值,这不是真的。这也必须在您的其他函数中更新 - 您之前已使用 atoi 函数对其进行了转换;因此,请使用该值。

所以该行应为:

lpszBuffer = (char*)malloc(nContentLength+1);

最后,要使用 memset ,您必须在源文件的开头#include <string.h>

此外,作为良好做法(特别是如果脚本运行了很长时间),不要忘记在完成脚本后free内存。也就是说,当您不再使用它时,分配了malloc的任何内容都应该free调用它。因此,如果您在整个函数中使用lpszBuffer,则在函数结束时只需执行free(lpszBuffer);

错误:从"char*"到"size_t"的转换无效

这是由于试图使用lpszContentLength(这是一个char*,在这种情况下是一串可能代表一个数字的字符串)作为size_t(通常是一个长整数)引起的。要解决此问题,您首先需要将lpszContentLength转换为整数值。我建议为此strtol(),因为它会检测错误 - 您需要处理这些错误。

查看教程,他们已经使用 atoi() .您还可以通过在他们尝试错误使用lpszContentLength的所有地方使用nContentLength来修复此错误。他们的代码一定从未经过测试。

请注意,atoi() 不会检测到错误 - 因此,完成本教程后,通过适当的错误检查更改为 strtol() 将是一个很好的学习练习。

<小时 />

错误:从"void*"到"char*"的转换无效

这是由于缺少在 malloc 的返回值上(char*)的强制转换导致的。在C++中,需要演员表:

lpszBuffer = (char*)malloc(convertedNumber+1); 
<小时 />

错误:未在此范围内声明"内存集"

这是由于不包含内存集的标头引起的。memset 的手册页告诉您需要添加:

#include <string.h>
<小时 />

错误:从"char*"到"size_t"的转换无效

错误:初始化"size_t fread(void*, size_t, size_t, FILE*)"的参数 3

这些都是由 lpszContentLength 是一个字符串字符引起的,当它需要是一个整数类型时。请参阅上面的第一个错误。