I'm experimenting with clang-tidy using the following file:
#include <stdio.h>
int main(int argc, char **argv)
{
int i=2; int j=1;
if (argc = 5) { return 2; }
while (i<argc) { j++; }
return 0;
}
I aim to detect the infinite loop with:
$ clang-tidy -checks=bugprone-infinite-loop main.c
but all that clang-tidy finds is the = instead of == thing:
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "main.c"
No compilation database found in /home/oren or any parent directory
fixed-compilation-database: Error while opening fixed database: No such file or directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
1 warning generated.
/home/oren/main.c:6:11: warning: using the result of an assignment as a condition without parentheses [clang-diagnostic-parentheses]
if (argc = 5) { return 2; }
~~~~ ^ ~
( == )
/home/oren/main.c:6:11: note: place parentheses around the assignment to silence this warning
/home/oren/main.c:6:11: note: use '==' to turn this assignment into an equality comparison
You are using a feature from a yet unreleased version of LLVM (10.0.0).
On my system (windows) your file works as expected:
>clang-tidy10 -checks=bugprone-infinite-loop infloop.c --
1 warning generated.
\infloop.c:6:5: warning: this loop is infinite; none of its con
dition variables (i, argc) are updated in the loop body [bugprone-infinite-loop]
while (i<argc) { j++; }
^
The only modification I did on the file is removing the unecessary #include. I also added -- (double dash) to the command to get rid of missing compilation database errors. I am using a prebuilt binary from https://llvm.org/builds/
My best guess here is that you are using an older build of clang-tidy where this is not detected. For reference my version is 10.0.0-e20a1e486e1, you can see yours by running:
>clang-tidy --version
I'd also check if you are actually running the check(s) you are expected to run via:
$ clang-tidy -checks=bugprone-infinite-loop main.c --list-checks
P.S. The warning message you got at first was clang-diagnostic based, this has nothing to do with clang-tidy but rather with clang compilation
Related
I am working on Windows and I am trying to write an array into a Ubuntu device using C++ in Visual Studio 2019. Here's a sample of my code:
int Run_WriteCalibTable(char *pcIPAddress, int iNumArgs, float *fArgs, int *iAnsSize, char *sAns)
...
...
...
char pcFolderName[256];
char pcFileName[256];
sprintf(pcFolderName, "%s\\%s",pcSavePath, pcUUTSerialNumber);
sprintf(pcFileName, "%s\\calib_rfclock.conf",pcFolderName);
// WRITE TABLE ON PC
FILE *pFileW;
pFileW = fopen(pcFileName,"wb");
fwrite(&CalibTable, sizeof(char), CalibTable.hdr.v1.u32Len, pFileW);
fclose(pFileW);
}
return 0;
However, I keep having this pop-up from Microsoft Visual C++ Debug Library that says:
Debug Assertion Failed:
Program:...
File: f:\dd\vctools\crt_bld\sefl_x86\crt\src\fwrite.c
Line: 77
Expression: (stream != NULL)
...
I found this thread and I tried logging in as root on my Ubuntu device. I also tried:
mount -o remount,rw /path/to/parent/directory
chmod 777 /path/to/parent/directory
And I can also create/edit manualy any file in the directory I'm trying to write into with my code, but I get the same error when running it.
Anyone knows what could cause this? I think it could be on the Windows side, but I don't know what I am doing wrong. Thanks a lot in advance.
You never check that opening the file succeeds - and it most likely fails, which is why you get the debug pop-up. Your use of \ as directory delimiters may be the only reason why it fails, but you should check to be sure.
I suggest that you use std::filesystem::path (C++17) to build your paths. That makes it easy to create paths in a portable way. You could also make use of a C++ standard std::ofstream to create the file. That way you don't need to close it afterwards. It closes automatically when it goes out of scope.
Example:
#include <cerrno>
#include <cstring>
#include <filesystem>
#include <fstream>
int Run_WriteCalibTable(char *pcIPAddress, int iNumArgs, float *fArgs,
int *iAnsSize, char *sAns)
{
...
// Build std::filesystem::paths:
auto pcFolderName = std::filesystem::path(pcSavePath) / pcUUTSerialNumber;
auto pcFileName = pcFolderName / "calib_rfclock.conf";
// only try to write to the file if opening the file succeeds:
if(std::ofstream pFileW(pcFileName, std::ios::binary); pFileW) {
// Successfully opened the file, now write to it:
pFileW.write(reinterpret_cast<const char*>(&CalibTable),
CalibTable.hdr.v1.u32Len);
} else {
// Opening the file failed, print the reason:
std::cerr << pcFileName << ": " << std::strerror(errno) << std::endl;
}
...
}
I need to be able to list the files in a directory, and so I'm trying to upgrade my C++ version in CodeBlocks to C++ 17 so i can use filesystem. To do this I followed the steps outlined at http://candcplusplus.com/enable-c17-in-code-blocks-mingw-gcc-for-all-version-with-pictures#:~:text=Enabling%20the%20C%2B%2B17,Create%20a%20project.
I didnt have to change much, CodeBlocks 20.03 and MinGW 8.1.0 are already installed. MinGW is already in my path from when I built wxWidgets. The Settings->Compiler...->Toolchain executables tab I didnt have to make any changes to, and appears in CodeBlocks as:
I also checked the box to use C++ 17 in compiler settings like so
I ran the test program on the website with the instructions and got "True!".
However when I change the basic test program to this, to try and use filesystem to read files in a directory, I get an error:
#include <iostream>
#include <filesystem>
using namespace std;
int main()
{
const int i=90;
if constexpr (i) //'if constexpr' is part of C++17
{
cout << "True!";
}
else
{
cout<<"False" ;
}
std::string path = "../MagicProgCPP/files/debug images/";
for (const auto & entry : filesystem::directory_iterator(path))
{
cout << entry.path() << std::endl;
}
cin.get();
return 0;
}
The program stops building, opens the file fs_path.h and stops on this line:
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
if (__p.is_absolute()
|| (__p.has_root_name() && __p.root_name() != root_name())) <----- ******STOPS HERE
operator=(__p);
else
{
string_type __pathname;
if (__p.has_root_directory())
__pathname = root_name().native();
else if (has_filename() || (!has_root_directory() && is_absolute()))
__pathname = _M_pathname + preferred_separator;
__pathname += __p.relative_path().native(); // XXX is this right?
_M_pathname.swap(__pathname);
_M_split_cmpts();
}
#else
// Much simpler, as any path with root-name or root-dir is absolute.
if (__p.is_absolute())
operator=(__p);
else
{
if (has_filename() || (_M_type == _Type::_Root_name))
_M_pathname += preferred_separator;
_M_pathname += __p.native();
_M_split_cmpts();
}
#endif
return *this;
}
I get this error in the build log:
C:\Program Files\CodeBlocks\MinGW\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\bits\fs_path.h|237|error: no match for 'operator!=' (operand types are 'std::filesystem::__cxx11::path' and 'std::filesystem::__cxx11::path')|
I'm prety confident the path exists as I entered it and there's files in it. The build log message suggests maybe I'm not using C++17? But when I click build, this is the line the program uses to build:
g++.exe -Wall -fexceptions -g -Wall -std=c++17 -c E:\testc17\main.cpp -o obj\Debug\main.o
What am I doing wrong? Thanks
The bug 78870 was fixed since 2018-07.
You should add to project options -> linker settings -> link libraries the following library: stdc++fs.
I tried to compile your code with MinGW gcc 8.1.0 (via CodeBlocks) and everything works well (clearly with another path, since I don't have the same directories as you).
You could also add a check on the existence of the search directory like this:
namespace fs = std::filesystem;
std::string mypath { "../MyDir" };
if(fs::exists(mypath))
{
for(const auto & entry : fs::directory_iterator(path))
{
cout << entry.path() << std::endl;
}
}
It appears that this exact problem is a known bug in mingw 8.1. The bug report is here: https://sourceforge.net/p/mingw-w64/bugs/737/
and has the error in the same location:
operator != is declared and defined in line 550, but referenced in line 237.
The problem is triggered by operator/= in line 233:
path& operator/=(const path& __p)
{
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
if (__p.is_absolute()
|| (__p.has_root_name() && __p.root_name() != root_name()))
operator=(__p);
else
{
string_type __pathname;
if (__p.has_root_directory())
__pathname = root_name().native();
else if (has_filename() || (!has_root_directory() && is_absolute()))
__pathname = _M_pathname + preferred_separator;
__pathname += __p.relative_path().native(); // XXX is this right?
_M_pathname.swap(__pathname);
_M_split_cmpts();
}
The bug report said this was fixed in master meaning you need to install a version of mingw with the fix applied. I believe the best method is to upgrade mingw to a version greater than 8.1
user4581301 commented above in the main question that the following link has instructions on how to get a mingw install: How to install MinGW-w64 and MSYS2?
I'm using tcclib to compile and run C code on the fly in my C++ project.
I'm using the binaries provided here https://bellard.org/tcc/
I then open a vs2019 developer prompt and run both those command
lib /def:libtcc\libtcc.def /out:libtcc.lib
cl /MD examples/libtcc_test.c -I libtcc libtcc.lib
My code builds fine, I'm using this code. This code is similar to the one found in the tcclib example, which is this one : https://repo.or.cz/tinycc.git/blob/HEAD:/tests/libtcc_test.c (this is another repo, but it's the same code.
The code I run is this one. This is inside an extern "C" {}.
int tcc_stuff(int argc, const char** argv) {
TCCState* s;
int i;
int (*func)(int);
s = tcc_new();
if (!s) {
fprintf(stderr, "Could not create tcc state\n");
exit(1);
}
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
for (i = 1; i < argc; ++i) {
const char* a = argv[i];
if (a[0] == '-') {
if (a[1] == 'B')
tcc_set_lib_path(s, a + 2);
else if (a[1] == 'I')
tcc_add_include_path(s, a + 2);
else if (a[1] == 'L')
tcc_add_library_path(s, a + 2);
}
}
/* MUST BE CALLED before any compilation */
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
{
const char* other_file = ReadFile2(argv[1]);
if (other_file == NULL)
{
printf("invalid filename %s\n", argv[1]);
return 1;
}
if (tcc_compile_string(s, other_file) == -1)
return 1;
}
/* as a test, we add symbols that the compiled program can use.
You may also open a dll with tcc_add_dll() and use symbols from that */
tcc_add_symbol(s, "add", add);
tcc_add_symbol(s, "hello", hello);
/* relocate the code */
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
return 1;
/* get entry symbol */
func = (int(*)(int))tcc_get_symbol(s, "foo");
if (!func)
return 1;
/* run the code */
msg(func(32));
//msg(func2(4));
/* delete the state */
tcc_delete(s);
return 0;
}
When running my code, TCC had the error
tcc: error: library 'libtcc1-32.a' not found
I fixed it by placing this file in the lib/ directory next to my .exe
I also copied the include/ folder to include stdio.h etc.
My question is: why does it need this file in a lib/ folder, instead of the provided tcclib.dll file? Is it possible to "ship" certain headers like stdio.h?
The question has no answer but 360 views, so I thought I'd reply.
The library doesn't necessarily need to be in that folder. To quote the author's command line docs, which still apply to the library,
-Ldir
Specify an additional static library path for the -l option. The default library paths are /usr/local/lib, /usr/lib and /lib.
I inferred your program to be a modified main() of libtcc_test.c & fixed it to the point of functioning. Then I used VS2022 to retrace your steps, put the .a files into the same folder as my new tests_libtcc_test.exe, then I ran this:
tests_libtcc_test c:/lang/tcc/examples/fib.c -Ic:/lang/tcc/include -L.
The library issue appears if I don't -L anything, and disappears if I include at least the ".".
And of course, you can drop the include folder into your redistributable and include it by default right from the code.
Because the tcc DLL is just another interface to the same compiler, it needs the same things tcc.exe would to build an executable; in this case, it needs the same libraries.
I have found this code as a bash autocomplete. But, it looks strange to me. What if I do not like to run the code at all. If I would like to type ./a.out then space (without entering) and then by pressing tab, I would like to see only two options apple and cherry and if I type a and press tab, then it autocomplete the option apple and similarly for c. Let's say only one of the two options are acceptable:
./a.out apple
./a.out cherry
where apple and cherry are options and not the name of the files in the directory. In the first case, I would like the program types that your option is apple and in the second case your option is cherry. In any other case, the program should print an error that the option is not valid.
All examples that I find on the internet such as what follows look like that you should run the program first, then it reacts. The while loop inside the main function collides with the normal functionality of the program. Have I misunderstood the readline library? Is the above-described application possible to implement by editing the following code?
// sudo apt-get install libreadline-dev
// g++ -std=c++11 main.cpp -lreadline
#include <iostream>
#include "readline/readline.h"
#include "readline/history.h"
using namespace std;
int main(int argc, char** argv)
{
const char *line;
while ((line = readline("? ")) != nullptr) {
cout << "[" << line << "]" << endl;
if (*line) add_history(line);
free(line);
}
// if(argc!=2)
// {
// cout<<"<exe> one_parameter"<<endl;
// return 1;
// }
// string option=argv[1];
// if(option=="apple" || option=="cherry")
// cout<<"Your option is "<<option<<endl;
// else
// {
// cout<<"Error: invalid option "<<option<<endl;
// return 1;
// }
return 0;
}
// partial answer - why you may want to invoke the app while doing the autocompletion
One way of implementing the autocomplete for an application is to have the application binary configure it (by having a flag that prints the instructions for autocomplete configuration or by just parsing the --help output of the application).
Schemataically:
complete -F $(./a.out --generate-autocomplete-config) ./a.out
This is why you might see the binary actually invoked as a part of autocomplete implementation.
This has nothing to do with your executable. You need to put this in a file and source (source autocomplete_file or . autocomplete_file) it in the bash.
_a_complete_()
{
local word=${COMP_WORDS[COMP_CWORD]}
local files='apple cherry'
COMPREPLY=( $( compgen -W "${files}" -- ${word} ) )
}
complete -F _a_complete_ ./a.out
Here a nice documentation can be found.
So I am trying to use LZO in my application. Here is how I have included it:
#include "lzoconf.h"
#include "lzodefs.h"
#include "lzo1x.h"
/* portability layer */
static const char *progname = NULL;
#define WANT_LZO_MALLOC 1
#define WANT_XMALLOC 1
#include "portab.h"
Then in the application I do:
if (lzo_init() != LZO_E_OK)
{
printf("internal error - lzo_init() failed !!!\n");
printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable '-DLZO_DEBUG' for diagnostics)\n");
return 4;
}
It compiles ok. No errors or warnings during compilation.
When I try to run my application though, there are two errors:
/home/richard/client/src/portab.h:145: undefined reference to `__lzo_align_gap'
Which points at this line in portab.h:
if (__lzo_align_gap(p, (lzo_uint) sizeof(lzo_align_t)) != 0)
{
printf("%s: C library problem: malloc() returned mis-aligned pointer!\n", progname);
exit(1);
}
return p;
And in my application:
/home/richard/client/src/main.cc:108: undefined reference to `__lzo_init_v2'
Which points to:
if (lzo_init() != LZO_E_OK)
{
printf("internal error - lzo_init() failed !!!\n");
printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable '-DLZO_DEBUG' for diagnostics)\n");
return 4;
}
I have all the header files inside my source directory:
config.h
lzo1x.h
lzoconf.h
lzodefs.h
miniacc.h
portab.h
portab_a.h
What am I doing wrong?
I am compiling my application in Ubuntu 10.10 in Anjuta ide.
Headers is not enough, you need to link to the libraries. Have you read the documentation?