I just started using dlls, but I haven't had this problem before, so it might not be dll connected. I am have KMP String-match algorithm implemented in c++ and I am calling it from c# using dll.
This is my export:
extern "C" __declspec (dllexport) const char* naive(const char* text, const char* str);
extern "C" __declspec (dllexport) const char* KMP(const char* text, const char* str);
My import:
[DllImport(#"dll_path", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr KMP([MarshalAs(UnmanagedType.LPStr)] string text, [MarshalAs(UnmanagedType.LPStr)] string str);
Calling from c#
string output = Marshal.PtrToStringAnsi(KMP(richTextBox1.Text, richTextBox2.Text));
And the c++ function:
const char* KMP(const char* text, const char* str)
{
int tL = strlen(text);
int sL = strlen(str);
/* Algorithm */
}
The exception is thrown right after the function is called. So I figured it's not the code implementation. The wired thing is it's only thrown when there is a '\n' new line in the second parameter (str), no matter where exactly. If there are no new lines it runs normally. The thing that confuses me the most is why just the second argument, both are identically declared and used. I also have implemented Naive algorithm, same story.
All the answers I found were only when a negative number was given as size to an array or an undeclared variable, but nothing on pointers. But I doubt it's anything similar, because when my search string (2nd parameter (str)) doesn't contain new line the code executes normally.
Any ideas ?
Thank you in front.
EDIT (body of function):
const char* KMP(const char* text, const char* str)
{
int tL = strlen(text);
int sL = strlen(str);
string match = "";
if (sL == 0 || tL == 0)
throw "both text and string must be larger than 0";
else if (sL > tL)
throw "the text must be longer than the string";
int tI = 0;
int col = 0, row = 0;
while (tI <= tL - sL)
{
int i = 0;
int tmpCol = -1;
int next = 1;
for (; i <= sL && text[i + tI] != '\0'; i++)
{
if (text[i + tI] == '\n')
{
row++;
tmpCol++;
}
if (text[i + tI] == str[0] && next == 1 && i > 0)
next = i;
if (text[i + tI] != str[i])
break;
}
if (i == sL)
{
match += to_string(row) + ',' + to_string(col) + ';';
}
tI += next;
col = tmpCol > -1 ? tmpCol : col + next;
}
char* c = new char[match.length() - 1];
c[match.length() - 1] = '\0';
for (int i = 0; i < match.length() - 1; i++)
c[i] = match[i];
return c;
}
Just change your code to handle no matches case, because runtime cannot allocate 0-1 = 0xFFFFFFFFF bytes. And now I have also changed your copy buffer allocation and loop code to avoid overwrite(as pointed by #HenkHoltermann):
...
if (match.length() == 0)
return "No matches";
// Allocate for all chars + \0 except the last semicolon
char* c = new char[match.length()];
c[match.length() - 1] = '\0';
// Copy all chars except the last semicolon
for (int i = 0; i < match.length() - 1; i++)
c[i] = match[i];
return c;
!It still does not copy the last semicolon, so if you need it then you will have to add one more symbol to the buffer.
P.S.: Also I see a few issues with your code:
You use C++ exceptions. While CLR will catch them as SEH (because VC++ uses SEH) it is still not a good idea overall - Throwing C++ exceptions across DLL boundaries
You use signed int for length int tL = strlen(text); and strlen returns unsigned size_t. It may not be an actual problem, but it is not a right way either.
Related
so I am using following Code to read from Memory:
public static extern bool ReadProcessMemory(IntPtr handle, IntPtr baseAddress, [Out] byte[] buffer, int size, out IntPtr numberOfBytesRead);
It outputs the memory Hex code as Byte Array using the code above:
buffer[0] = 01;
buffer[1] = 2D;
buffer[2] = F2;
I want to search in a certain range of the Hex Code for a certain Hex Array.
To do that I would like to use the "KMP Algorithm for Pattern Searching".
Currently I am using the following code to achieve that:
byte[] moduleBytes = {0};
IntPtr bytesRead;
ReadProcessMemory(process.Handle, baseAddress, moduleBytes, moduleBytes.Length, out bytesRead);
string buffer = "";
foreach (byte bytesfrommemory in moduleBytes)
{
buffer += bytesfrommemory.ToString("X");;
}
//algorithm
string data = buffer;
int[] value = SearchString(data, pattern);
foreach (int entry in value)
{
Console.WriteLine(entry); //Outputs the offset where it found the code
}
The issue with that is that looping trough each byte to add it to the buffer string takes ages with +1000 bytes. Is there a faster way to "convert" the byte array from array to string without actually converting it as I still need the raw byte array just as string?
I tried it with the following code, but it converts it to something different:
char[] characters = moduleBytes.Select(o => (char)o).ToArray();
string buffer = new string(characters);
Thanks for any help :)
Alexei's comment is on point; you are converting bytes to a string to run a search algorithm that will convert the string to char array (i.e. a byte array, i.e. what you started with) in order to do its work. Finding a byte array within a byte array using KMP is the same as finding a string within a string
To demonstrate my point I casted around for an implementation of KMP that works on strings. I found one at Geeks For Geeks and swapped it from working on strings, to working on bytes, literally just just editing the type in the method calls; string has a Length and can be indexed like an array, byte array has a Length and can be indexed because it is an array etc - there is no more needed to make this version work:
// C# program for implementation of KMP pattern
// searching algorithm
using System;
public class GFG {
void KMPSearch(byte[] pat, byte[] txt)
{
int M = pat.Length;
int N = txt.Length;
// create lps[] that will hold the longest
// prefix suffix values for pattern
int[] lps = new int[M];
int j = 0; // index for pat[]
// Preprocess the pattern (calculate lps[]
// array)
computeLPSArray(pat, M, lps);
int i = 0; // index for txt[]
while (i < N) {
if (pat[j] == txt[i]) {
j++;
i++;
}
if (j == M) {
Console.Write("Found pattern "
+ "at index " + (i - j));
j = lps[j - 1];
}
// mismatch after j matches
else if (i < N && pat[j] != txt[i]) {
// Do not match lps[0..lps[j-1]] characters,
// they will match anyway
if (j != 0)
j = lps[j - 1];
else
i = i + 1;
}
}
}
void computeLPSArray(byte[] pat, int M, int[] lps)
{
// length of the previous longest prefix suffix
int len = 0;
int i = 1;
lps[0] = 0; // lps[0] is always 0
// the loop calculates lps[i] for i = 1 to M-1
while (i < M) {
if (pat[i] == pat[len]) {
len++;
lps[i] = len;
i++;
}
else // (pat[i] != pat[len])
{
// This is tricky. Consider the example.
// AAACAAAA and i = 7. The idea is similar
// to search step.
if (len != 0) {
len = lps[len - 1];
// Also, note that we do not increment
// i here
}
else // if (len == 0)
{
lps[i] = len;
i++;
}
}
}
}
// Driver program to test above function
public static void Main()
{
string txt = System.Text.Encoding.ASCII.GetBytes("ABABDABACDABABCABAB");
string pat = System.Text.Encoding.ASCII.GetBytes("ABABCABAB");
new GFG().KMPSearch(pat, txt);
}
}
// This code has been contributed by Amit Khandelwal.
The biggest work (most number of keys typed) is using System.Text.Encoding.ASCII.GetBytes to get a pair of byte arrays to feed in 😀
Take away point; don't convert your memory bytes at all - convert your search term to bytes and search it in the memory bytes
Disclaimer: I offer zero guarantee that this is a correct implementation of KMP that functions adequately for your use case. It seems to work, but I'm only pointing out that you don't need to convert to strings and back again to operate code that fundamentally can search bytes in exactly the same way as it searches strings
I am trying to migrate a code written in C# to C for better performance and to be able to use it in another software as it supports C based DLL.
I have this function in C# which performs as expected
private byte[] authDataExtract(byte[] concatenatedData)
{
try
{
byte[] authData = null;
authData = new byte[concatenatedData.Length - 10];
int blockCount = 0;
while (true)
{
if (concatenatedData.Length - 10 - blockCount < 4)
break;
else if (concatenatedData.Length - 10 - blockCount >= 4)
{
if ((isAllZero(concatenatedData, blockCount) == true) || (isAllff(concatenatedData, blockCount) == true)) //Modified to handle 0xFF padding - Sudhanwa
break;
int dlc = int.Parse(concatenatedData[blockCount + 3].ToString("X2"), System.Globalization.NumberStyles.HexNumber); //Modified to handle exceptiion in case of Padding CR - Sudhanwa
//int dlc = int.Parse(bytetostring(concatenatedData[blockCount + 3]));
if ((dlc > concatenatedData.Length - 10 - blockCount))
{
authData = new byte[concatenatedData.Length - 10];
Buffer.BlockCopy(concatenatedData, 0, authData, 0, concatenatedData.Length - 10);
blockCount = concatenatedData.Length - 10;
break;
}
authData = new byte[blockCount + 4 + dlc];
Buffer.BlockCopy(concatenatedData, 0, authData, 0, blockCount + 4 + dlc);
blockCount += dlc + 4;
}
}
return authData;
}
catch (Exception)
{
throw;
}
}
I want to write equivalent C code for this
My current C code is
void authDataExtract(unsigned char payload [],unsigned int size_payload,unsigned char * arr)
{
//unsigned char rec_tMAC [8];
int blockcount=0;
int dlc=0;
//unsigned char* arr= NULL;
//memcpy(&rec_tMAC[0],&payload[size_payload-8],8);
//printArr(rec_tMAC,8);
while (1)
{
if (size_payload- 10 - blockcount < 4)
break;
else if (size_payload - 10 - blockcount >= 4)
{
if ((isAllZero(payload,size_payload,blockcount) == true) ||
(isAllff(payload,size_payload, blockcount) == true))
break;
dlc= payload[blockcount + 3];
if ((dlc > size_payload - 10 - blockcount))
{
arr = (unsigned char*)calloc(size_payload-10,sizeof(unsigned char));
memcpy(arr,payload,size_payload-10);
blockcount = size_payload - 10;
break;
}
arr = (unsigned char*)calloc(blockcount + 4 + dlc,sizeof(unsigned char));
memcpy(arr,payload,blockcount + 4 + dlc);
blockcount += dlc + 4;
}
}
}
But it is giving exceptions with pointer .I believe I have an issue
with dynamic memory allocation.
Assuming the logic inc C# code is correct ,request your help to have exact same logic with C function.
Thanks in advance.
Do you see that C# function is returning byte[]
private byte[] authDataExtract(byte[] concatenatedData)
But C function is not.
void authDataExtract(unsigned char payload [],unsigned int size_payload,unsigned char * arr)
Note that arr is new variable and it is local to authDataExtract
function. It has no effect on the caller function.
Try as below.
unsigned char* authDataExtract(unsigned char payload [],unsigned int size_payload,unsigned char * arr) {
while(1) {
...
}
return arr;
}
from main
unsigned char *p = authDataExtract(….);
if (!p) error;
You could also use pointer to pointer but I leave that to you.
I have this code (snipet) and it runs through and works, but after leaving the whole procedure procedureInAClass() and going on with next code it crashes: "Bad_module_error". I don't see the error.
public void procedureInAClass(){ //this code is in a Class, it works but after leaving whole procedure it crashes
char** comment=(char**)Marshal.AllocHGlobal(sizeof(char*)); //comment is in Code a class Member
string aval="some chars in a string";
SToCP(val, comment) ; //value of String to *comment
CPToS(comment); //**comment to string
}
//this part is in a static class
public static void SToCP(string s, char** c)//writes string s in *c
{
*c = SToCP(s);
}
public static char* SToCP(string s)
{
char* ret= (char*)Marshal.AllocHGlobal( sizeof(char) * (s.Length +1));
int i;
byte se = sizeof(char);
for (i = 0; i < s.Length; i++)
*(ret + se * i) = s[i];
*(ret + s.Length * se) = '\0';
return ret;
}
public static String CPToS(char** c)
{
return CPToS(*c); //passing the pointer char* which is holded by char** c
}
public static String CPToS(char* c)
{
string ret = "";
byte s = sizeof(char);//char is two bytes long
int i = 0;
while (*(c + s * i) != '\0')//zero terminated string
ret += *(c + s * i++);
return ret;
}
Your problem is that you are multiplying your index i by the sizeof(char*) but treating that as a char*. Adding 1 to a char* adds the size of a char (2 bytes) to the pointer. You were writing every other character, then continuing to overwrite memory after your string allocation because of going too far.
Try this instead:
public static char* SToCP(string s) {
char* ret = (char*)Marshal.AllocHGlobal(sizeof(char) * (s.Length + 1));
char* p = ret;
for (int i = 0; i < s.Length; i++)
*(p++) = s[i];
*(p++) = '\0';
return ret;
}
Of course your CPToS method is also wrong, so if you fix SToCP to correctly not write over other character, you will need to fix CPToS as well otherwise it will return the wrong string back.
Here's a fixed version of CPToS to match:
public static String CPToS(char* c) {
string ret = "";
int i = 0;
while (*(c + i) != '\0')//zero terminated string
ret += *(c + i++);
return ret;
}
SToCP was causing the stack to be screwed up and causing the crash, though.
I have a project that is almost near completion aside from a couple of stubborn but probably simple error Im receiving. I am by know means knowledgeable of C and me getting this project this far is a miracle. Im hoping someone can detect what it is I am missing in my code. Here is the view of the errors and below is the code.
private void button1_Click(object sender, EventArgs e)
{
Random rnd = new Random();
StringBuilder bin = new StringBuilder();
int buf = 0;
int bufLen = 0;
int left = 53;
for (int i = 106; i >= 1; i += -1)
{
buf <<= 1;
if (rnd.Next(i) < left)
{
buf += 1;
left -= 1;
}
bufLen += 1;
if (bufLen == 4)
{
bin.Append("0123456789ABCDEF"(buf));
bufLen = 0;
buf = 0;
}
}
string b = bin.ToString();
bin.Append("048c"(buf));
System.Security.Cryptography.SHA1Managed m = new System.Security.Cryptography.SHA1Managed();
byte[] hash = m.ComputeHash(Encoding.UTF8.GetBytes(b));
//replace first two bits in hash with bits from buf
hash(0) = Convert.ToByte(hash(0) & 0x3f | (buf * 64));
//append 24 bits from hash
b = b.Substring(0, 26) + BitConverter.ToString(hash, 0, 3).Replace("-", string.Empty);
}
}
}
x(y) means "call x with y as a parameter".
You have written "0123456789ABCDEF"(buf). "0123456789ABCDEF" isn't a function (or a functor) so you can't call it.
Perhaps you meant to index it, with "0123456789ABCDEF"[buf]? This returns the buf'th character from "0123456789ABCDEF", which is buf in hexadecimal as long as buf is between 0 and 15.
You can't concatenate a string literal with a string variable.
#include <iostream>
using std::cout;
void concatenate(const std::string& s)
{
cout << "In concatenate, string passed is: "
<< s
<< "\n";
}
int main(void)
{
std::string world = " World!\n";
concatenate("Hello"(world));
return 0;
}
Thomas#HastaLaVista ~/concatenation
# g++ -o main.exe main.cpp
main.cpp: In function `int main()':
**main.cpp:15: error: `"Hello"' cannot be used as a function**
Thomas#HastaLaVista ~/concatenation
# g++ --version
g++ (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
You will need a temporary string variable:
if (bufLen == 4)
{
std::string temp("01234567890ABCDEF");
temp += buf;
bin.Append(temp);
bufLen = 0;
buf = 0;
}
I have the following code in c# which reverses a string:
char[] charArray = s.ToCharArray();
int len = s.Length - 1;
for (int i = 0; i < len; i++, len--)
{
charArray[i] ^= charArray[len];
charArray[len] ^= charArray[i];
charArray[i] ^= charArray[len];
}
return new string(charArray);
I am trying to convert it to C++ as an intellectual exercise more than anything. Here is what I have so far:
void main(void)
{
char* str = "testing";
char* result;
int len;
len = strlen(str);
if (len <= 12)
{
result = new char[strlen(str)];
for (int i = 0; i < len; i++, len--)
{
result[i] ^= str[len];
result[len] ^= str[i];
result[i] ^= str[len];
}
}
else{
std::reverse(str, &str[strlen(str)]);
}
cout << endl << result << endl;
// cleanup
str = NULL;
result = NULL;
}
In .Net if the string is <= 12 (I think it's twelve) xor is faster than array reverse. Source - Sam Saffron I am basically trying to see if it still holds up in C++.
The string comes out in a weird format (════╣¥¿ë²²² to be precise).
Any ideas?
Note: I know the else statement doesn't work, I'll figure that bit out after ;)
Note 2: I am probably doing this completely wrong, so feel free to point absolutely anything out
Update
Thanks to everyone that has participated. I haven't played with c++ in a fair few years (and it shows) and thought it would be quiet easy to convert but obviously not. Think it's best I abandon this idea. Thanks again
A few things:
result = new char[strlen(str)];
Should be
result = new char[len + 1];
len because you've already calculated the length of str, and + 1 to make room for the NUL terminator.
Secondly, you need to copy the string into result before operating on it, because otherwise your array is full of garbage otherwise:
strcpy(result, str);
Thirdly,
std::reverse(str, &str[strlen(str)]);
Is wrong for two reasons: one, because you can't modify string literals, and two, because you should be using result:
std::reverse(result, result + len);
But if you do that, you also need to copy str into result first.
And lastly, setting a pointer to NULL does not deallocate the memory it points to. You have to
delete[] result; // delete[] because new[]
Note that for this to work even when the else is taken (and therefore result is not made to point to allocated memory), you need to do
char* result = NULL; // delete[] is defined as a nop on NULL pointers
All the above applies if you're sure you want to use C-strings. Once you get the hang of pointers, you can graduate to std::string:
std::string str("testing");
std::reverse(std::begin(str), std::end(str)); // or if you don't want to do it in-place,
// std::string result(str.rbegin(), str.rend());
xor swap is for swapping. If you're copying into a result array then that's assigning, not swapping. Also, you must only iterate half-way through the array, otherwise you swap it twice.
Here is a translation of the C# code:
#include <iostream>
#include <algorithm>
int main(void)
{
char str[] = "testing"; // arrays have automatic storage - no need to new/delete
const size_t str_len = sizeof(str)-1; // sizeof(str) returns size of the array
if (str_len <= 12) // because str_len is a constant expression, the other branch will be compiled-out
{
// this should probably use iterators (pointers) but oh well
for (size_t i = 0, len = str_len-1; i < str_len/2; i++, len--)
{
str[i] ^= str[len];
str[len] ^= str[i];
str[i] ^= str[len];
}
}
else{
std::reverse(str, str + str_len); // str decays to a pointer
}
std::cout << str << '\n'; // don't use endl if you don't need to flush
}
This is pretty bad code. Just use std::string and std::reverse. It is faster than xor and only 2 lines long.
std::string str = "testing"
std::reverse(str.begin(), str.end());
A better way of doing it, more C++, less C
std::string mystring = "testing";
std::string reversed;
for(std::string::iterator str_it = mystring.rbegin(); str_it != mystring.rend(); ++str_it)
{
reversed += *str_it;
}
std::cout << reversed << std::endl;